library(swimplot) library(coxphf) library(grid) library(gtable) library(readr) library(mosaic) library(dplyr) library(survival) library(survminer) library(ggplot2) library(scales) library(coxphf) library(ggthemes) library(tidyverse) library(gtsummary) library(flextable) library(parameters) library(car) library(ComplexHeatmap) library(tidyverse) library(readxl) library(survival) library(janitor) library(openxlsx) library(writexl) library(rms) library(pROC) library(DT)

#ctDNA Detection rate by Stage and Window

#Baseline
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.Base %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.Base == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.Base, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.Base == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#C2D1
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.C2D1 <- factor(circ_data$ctDNA.C2D1, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.C2D1 %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.C2D1 == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.C2D1, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.C2D1 == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#post-NAC Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.postNAC %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.postNAC == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.postNAC, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.postNAC == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#MRD Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.MRD %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.MRD == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.MRD, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.MRD == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#On-treatment
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.onACT <- factor(circ_data$ctDNA.onACT, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.onACT %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.onACT == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.onACT, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.onACT == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Surveillance Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.surveillance <- factor(circ_data$ctDNA.surveillance, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.surveillance %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.surveillance == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.surveillance, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.surveillance == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Post-ACT Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.postACT <- factor(circ_data$ctDNA.postACT, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.postACT %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.postACT == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.postACT, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.postACT == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Post-relapse Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.postRelapse <- factor(circ_data$ctDNA.postRelapse, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.postRelapse %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.postRelapse == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.postRelapse, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.postRelapse == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Neoadjuvant Treatment duration

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included == TRUE, ]

circ_data$NAC.Start <- as.Date(circ_data$NAC.Start, format="%m/%d/%Y")
circ_data$NAC.End <- as.Date(circ_data$NAC.End, format="%m/%d/%Y")
circ_data$NAC.Duration <- as.numeric(difftime(circ_data$NAC.End, circ_data$NAC.Start, units="days"))
median_duration <- median(circ_data$NAC.Duration, na.rm=TRUE)
range_duration <- range(circ_data$NAC.Duration, na.rm=TRUE)
Q1 <- quantile(circ_data$NAC.Duration, 0.25, na.rm=TRUE)
Q3 <- quantile(circ_data$NAC.Duration, 0.75, na.rm=TRUE)
IQR_value <- IQR(circ_data$NAC.Duration, na.rm=TRUE)
cat("Median NAC Duration:", median_duration, "days\n")
Median NAC Duration: 43 days
cat("Range of NAC Duration:", range_duration[1], "-", range_duration[2], "days\n")
Range of NAC Duration: 28 - 242 days
cat("Q1 (25th percentile):", Q1, "days\n")
Q1 (25th percentile): 42 days
cat("Q3 (75th percentile):", Q3, "days\n")
Q3 (75th percentile): 56 days
cat("Interquartile Range (IQR):", IQR_value, "days\n")
Interquartile Range (IQR): 14 days

#Time of ctDNA draws from start and end of neodjuvant treatment

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included == TRUE, ]

circ_data$NAC.Start <- as.Date(circ_data$NAC.Start, format="%m/%d/%Y")
circ_data$NAC.End <- as.Date(circ_data$NAC.End, format="%m/%d/%Y")
circ_data$ctDNA.C2D1.Date <- as.Date(circ_data$ctDNA.C2D1.Date, format="%m/%d/%Y")
circ_data$ctDNA.postNAC.Date <- as.Date(circ_data$ctDNA.postNAC.Date, format="%m/%d/%Y")

circ_data$Time_to_ctDNA_C2D1 <- as.numeric(difftime(circ_data$ctDNA.C2D1.Date, circ_data$NAC.Start, units="days"))
circ_data$Time_to_ctDNA_postNAC <- as.numeric(difftime(circ_data$ctDNA.postNAC.Date, circ_data$NAC.End, units="days"))

median_ctDNA_C2D1 <- median(circ_data$Time_to_ctDNA_C2D1, na.rm=TRUE)
range_ctDNA_C2D1 <- range(circ_data$Time_to_ctDNA_C2D1, na.rm=TRUE)
Q1_ctDNA_C2D1 <- quantile(circ_data$Time_to_ctDNA_C2D1, 0.25, na.rm=TRUE)
Q3_ctDNA_C2D1 <- quantile(circ_data$Time_to_ctDNA_C2D1, 0.75, na.rm=TRUE)
IQR_ctDNA_C2D1 <- IQR(circ_data$Time_to_ctDNA_C2D1, na.rm=TRUE)
median_ctDNA_postNAC <- median(circ_data$Time_to_ctDNA_postNAC, na.rm=TRUE)
range_ctDNA_postNAC <- range(circ_data$Time_to_ctDNA_postNAC, na.rm=TRUE)
Q1_ctDNA_postNAC <- quantile(circ_data$Time_to_ctDNA_postNAC, 0.25, na.rm=TRUE)
Q3_ctDNA_postNAC <- quantile(circ_data$Time_to_ctDNA_postNAC, 0.75, na.rm=TRUE)
IQR_ctDNA_postNAC <- IQR(circ_data$Time_to_ctDNA_postNAC, na.rm=TRUE)
cat("Median time from NAC start to ctDNA draw during NAC:", median_ctDNA_C2D1, "days\n")
Median time from NAC start to ctDNA draw during NAC: 14 days
cat("Range:", range_ctDNA_C2D1[1], "-", range_ctDNA_C2D1[2], "days\n")
Range: 10 - 111 days
cat("Q1 (25th percentile):", Q1_ctDNA_C2D1, "days\n")
Q1 (25th percentile): 14 days
cat("Q3 (75th percentile):", Q3_ctDNA_C2D1, "days\n")
Q3 (75th percentile): 28 days
cat("Interquartile Range (IQR):", IQR_ctDNA_C2D1, "days\n\n")
Interquartile Range (IQR): 14 days
cat("Median time from NAC end to ctDNA draw post-NAC:", median_ctDNA_postNAC, "days\n")
Median time from NAC end to ctDNA draw post-NAC: 0 days
cat("Range:", range_ctDNA_postNAC[1], "-", range_ctDNA_postNAC[2], "days\n")
Range: -4 - 64 days
cat("Q1 (25th percentile):", Q1_ctDNA_postNAC, "days\n")
Q1 (25th percentile): 0 days
cat("Q3 (75th percentile):", Q3_ctDNA_postNAC, "days\n")
Q3 (75th percentile): 12 days
cat("Interquartile Range (IQR):", IQR_ctDNA_postNAC, "days\n")
Interquartile Range (IQR): 12 days

#Demographics Table

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data_subset <- circ_data %>%
  select(
    Age,
    Gender,
    PrimSite,
    NAC,
    NAC.Regimen,
    TRG.Mandard,
    TNM,
    Stage,
    Grade,
    Lauren.Class,
    Margins,
    ACT,
    ACT.Regimen,
    DFS.Event,
    OS.Event,
    FU.months) %>%
  mutate(
    Age = as.numeric(Age),
    Gender = factor(Gender, levels = c("Male", "Female")),
    PrimSite = factor(PrimSite, levels = c("Stomach", "G/J", "Oesophagus")),
    NAC = factor(NAC, levels = c("TRUE", "FALSE"), labels = c("Neoadjuvant Therapy", "Upfront Surgery")),
    NAC.Regimen = factor(NAC.Regimen),
    TRG.Mandard = factor(TRG.Mandard, levels = c("TRG1","TRG2", "TRG3", "TRG4", "TRG5")),
    TNM = factor(TNM, levels = c("T0-TisN0M0","T1-T2N0", "T2-T3N0-N1", "T2N1-N2", "T3N2-N3", "T4N0-N1", "T4N2-N3")),
    Stage = factor(Stage, levels = c("0","I","II", "III")),
    Grade = factor(Grade, levels = c("G1", "G2", "G3")),
    Lauren.Class = factor(Lauren.Class),
    Margins = factor(Margins, levels = c("R0", "R1")),
    ACT = factor(ACT, levels = c("TRUE", "FALSE"), labels = c("Adjuvant Treatment", "Observation")),
    ACT.Regimen = factor(ACT.Regimen),
    DFS.Event = factor(DFS.Event, levels = c("TRUE", "FALSE"), labels = c("Recurrence", "No Recurrence")),
    OS.Event = factor(OS.Event, levels = c("TRUE", "FALSE"), labels = c("Deceased", "Alive")),
    FU.months = as.numeric(FU.months))
table1 <- circ_data_subset %>%
  tbl_summary(
    statistic = list(
      all_continuous() ~ "{median} ({min} - {max})",
      all_categorical() ~ "{n} ({p}%)")) %>%
  bold_labels()
table1
Characteristic N = 621
Age 66 (34 - 86)
Gender
    Male 39 (63%)
    Female 23 (37%)
PrimSite
    Stomach 38 (61%)
    G/J 24 (39%)
    Oesophagus 0 (0%)
NAC
    Neoadjuvant Therapy 55 (89%)
    Upfront Surgery 7 (11%)
NAC.Regimen
     7 (11%)
    Chemoimmunotherapy 7 (11%)
    Chemotherapy 47 (76%)
    Radiotherapy 1 (1.6%)
TRG.Mandard
    TRG1 3 (5.5%)
    TRG2 8 (15%)
    TRG3 21 (38%)
    TRG4 16 (29%)
    TRG5 7 (13%)
    Unknown 7
TNM
    T0-TisN0M0 3 (4.8%)
    T1-T2N0 16 (26%)
    T2-T3N0-N1 17 (27%)
    T2N1-N2 2 (3.2%)
    T3N2-N3 8 (13%)
    T4N0-N1 9 (15%)
    T4N2-N3 7 (11%)
Stage
    0 3 (4.8%)
    I 16 (26%)
    II 26 (42%)
    III 17 (27%)
Grade
    G1 11 (28%)
    G2 21 (53%)
    G3 8 (20%)
    Unknown 22
Lauren.Class
     5 (8.1%)
    Diffuse 18 (29%)
    Intestinal 34 (55%)
    Mixed 5 (8.1%)
Margins
    R0 61 (98%)
    R1 1 (1.6%)
ACT
    Adjuvant Treatment 53 (85%)
    Observation 9 (15%)
ACT.Regimen
     9 (15%)
    Chemoimmunotherapy 4 (6.5%)
    Chemotherapy 48 (77%)
    Immunotherapy 1 (1.6%)
DFS.Event
    Recurrence 29 (47%)
    No Recurrence 33 (53%)
OS.Event
    Deceased 19 (31%)
    Alive 43 (69%)
FU.months 29 (2 - 93)
1 Median (Min - Max); n (%)
fit1 <- as_flex_table(
  table1,
  include = everything(),
  return_calls = FALSE
)
fit1

Characteristic

N = 621

Age

66 (34 - 86)

Gender

Male

39 (63%)

Female

23 (37%)

PrimSite

Stomach

38 (61%)

G/J

24 (39%)

Oesophagus

0 (0%)

NAC

Neoadjuvant Therapy

55 (89%)

Upfront Surgery

7 (11%)

NAC.Regimen

7 (11%)

Chemoimmunotherapy

7 (11%)

Chemotherapy

47 (76%)

Radiotherapy

1 (1.6%)

TRG.Mandard

TRG1

3 (5.5%)

TRG2

8 (15%)

TRG3

21 (38%)

TRG4

16 (29%)

TRG5

7 (13%)

Unknown

7

TNM

T0-TisN0M0

3 (4.8%)

T1-T2N0

16 (26%)

T2-T3N0-N1

17 (27%)

T2N1-N2

2 (3.2%)

T3N2-N3

8 (13%)

T4N0-N1

9 (15%)

T4N2-N3

7 (11%)

Stage

0

3 (4.8%)

I

16 (26%)

II

26 (42%)

III

17 (27%)

Grade

G1

11 (28%)

G2

21 (53%)

G3

8 (20%)

Unknown

22

Lauren.Class

5 (8.1%)

Diffuse

18 (29%)

Intestinal

34 (55%)

Mixed

5 (8.1%)

Margins

R0

61 (98%)

R1

1 (1.6%)

ACT

Adjuvant Treatment

53 (85%)

Observation

9 (15%)

ACT.Regimen

9 (15%)

Chemoimmunotherapy

4 (6.5%)

Chemotherapy

48 (77%)

Immunotherapy

1 (1.6%)

DFS.Event

Recurrence

29 (47%)

No Recurrence

33 (53%)

OS.Event

Deceased

19 (31%)

Alive

43 (69%)

FU.months

29 (2 - 93)

1Median (Min - Max); n (%)

save_as_docx(fit1, path= "~/Downloads/table1.docx")

#Demographics Table for those that included vs excluded from the study

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")

circ_data_subset1 <- circ_data %>%
  select(
    Age,
    Gender,
    PrimSite,
    NAC,
    NAC.Regimen,
    TRG.Mandard,
    TNM,
    Stage,
    Grade,
    Lauren.Class,
    Margins,
    ACT,
    ACT.Regimen,
    DFS.Event,
    OS.Event,
    FU.months) %>%
  mutate(
    Age = as.numeric(Age),
    Gender = factor(Gender, levels = c("Male", "Female")),
    PrimSite = factor(PrimSite, levels = c("Stomach", "G/J", "Oesophagus")),
    NAC = factor(NAC, levels = c("TRUE", "FALSE"), labels = c("Neoadjuvant Therapy", "Upfront Surgery")),
    NAC.Regimen = factor(NAC.Regimen),
    TRG.Mandard = factor(TRG.Mandard, levels = c("TRG1","TRG2", "TRG3", "TRG4", "TRG5")),
    TNM = factor(TNM, levels = c("T0-TisN0M0","T1-T2N0", "T2-T3N0-N1", "T2N1-N2", "T3N2-N3", "T4N0-N1", "T4N2-N3")),
    Stage = factor(Stage, levels = c("0","I","II", "III")),
    Grade = factor(Grade, levels = c("G1", "G2", "G3")),
    Lauren.Class = factor(Lauren.Class),
    Margins = factor(Margins, levels = c("R0", "R1")),
    ACT = factor(ACT, levels = c("TRUE", "FALSE"), labels = c("Adjuvant Treatment", "Observation")),
    ACT.Regimen = factor(ACT.Regimen),
    DFS.Event = factor(DFS.Event, levels = c("TRUE", "FALSE"), labels = c("Recurrence", "No Recurrence")),
    OS.Event = factor(OS.Event, levels = c("TRUE", "FALSE"), labels = c("Deceased", "Alive")),
    FU.months = as.numeric(FU.months))

circ_data1 <- read.csv("PLAGAST_Clinical Data.csv")

circ_data_subset2 <- circ_data %>%
  select(
    Age,
    Gender,
    PrimSite,
    NAC,
    NAC.Regimen,
    TRG.Mandard,
    TNM,
    Stage,
    Grade,
    Lauren.Class,
    Margins,
    ACT,
    ACT.Regimen,
    DFS.Event,
    OS.Event,
    FU.months,
    Included) %>%
  mutate(
    Age = as.numeric(Age),
    Gender = factor(Gender, levels = c("Male", "Female")),
    PrimSite = factor(PrimSite, levels = c("Stomach", "G/J", "Oesophagus")),
    NAC = factor(NAC, levels = c("TRUE", "FALSE"), labels = c("Neoadjuvant Therapy", "Upfront Surgery")),
    NAC.Regimen = factor(NAC.Regimen),
    TRG.Mandard = factor(TRG.Mandard, levels = c("TRG1","TRG2", "TRG3", "TRG4", "TRG5")),
    TNM = factor(TNM, levels = c("T0-TisN0M0","T1-T2N0", "T2-T3N0-N1", "T2N1-N2", "T3N2-N3", "T4N0-N1", "T4N2-N3")),
    Stage = factor(Stage, levels = c("0","I","II", "III")),
    Grade = factor(Grade, levels = c("G1", "G2", "G3")),
    Lauren.Class = factor(Lauren.Class),
    Margins = factor(Margins, levels = c("R0", "R1")),
    ACT = factor(ACT, levels = c("TRUE", "FALSE"), labels = c("Adjuvant Treatment", "Observation")),
    ACT.Regimen = factor(ACT.Regimen),
    DFS.Event = factor(DFS.Event, levels = c("TRUE", "FALSE"), labels = c("Recurrence", "No Recurrence")),
    OS.Event = factor(OS.Event, levels = c("TRUE", "FALSE"), labels = c("Deceased", "Alive")),
    FU.months = as.numeric(FU.months),
    Included = factor(Included, levels = c("TRUE", "FALSE"), labels = c("Included", "Excluded")))
Overall <- circ_data_subset1 %>%
  tbl_summary(
    statistic = list(
      all_continuous() ~ "{median} ({min} - {max})",
      all_categorical() ~ "{n} ({p}%)")) %>%
  bold_labels()
Overall
Characteristic N = 821
Age 67 (34 - 86)
Gender
    Male 51 (62%)
    Female 31 (38%)
PrimSite
    Stomach 54 (66%)
    G/J 28 (34%)
    Oesophagus 0 (0%)
NAC
    Neoadjuvant Therapy 74 (90%)
    Upfront Surgery 8 (9.8%)
NAC.Regimen
     8 (9.8%)
    Chemoimmunotherapy 8 (9.8%)
    Chemotherapy 65 (79%)
    Radiotherapy 1 (1.2%)
TRG.Mandard
    TRG1 4 (5.6%)
    TRG2 14 (19%)
    TRG3 26 (36%)
    TRG4 19 (26%)
    TRG5 9 (13%)
    Unknown 10
TNM
    T0-TisN0M0 3 (3.7%)
    T1-T2N0 25 (30%)
    T2-T3N0-N1 21 (26%)
    T2N1-N2 4 (4.9%)
    T3N2-N3 9 (11%)
    T4N0-N1 12 (15%)
    T4N2-N3 8 (9.8%)
Stage
    0 3 (3.7%)
    I 25 (30%)
    II 33 (40%)
    III 21 (26%)
Grade
    G1 14 (26%)
    G2 27 (50%)
    G3 13 (24%)
    Unknown 28
Lauren.Class
     8 (9.8%)
    Diffuse 21 (26%)
    Intestinal 45 (55%)
    Mixed 8 (9.8%)
Margins
    R0 78 (95%)
    R1 4 (4.9%)
ACT
    Adjuvant Treatment 68 (83%)
    Observation 14 (17%)
ACT.Regimen
     19 (23%)
    Chemoimmunotherapy 4 (4.9%)
    Chemotherapy 58 (71%)
    Immunotherapy 1 (1.2%)
DFS.Event
    Recurrence 37 (45%)
    No Recurrence 45 (55%)
OS.Event
    Deceased 25 (30%)
    Alive 57 (70%)
FU.months 32 (2 - 93)
1 Median (Min - Max); n (%)

ByctDNA_MRD <- circ_data_subset2 %>%
  tbl_summary(
    by = Included, # Subgroup by Included
    statistic = list(
      all_continuous() ~ "{median} ({min} - {max})",
      all_categorical() ~ "{n} ({p}%)")) %>%
  add_p(test = all_categorical() ~ "fisher.test", pvalue_fun = ~style_pvalue(p.adjust(.x, method = "bonferroni"))) %>%
  bold_labels()
ByctDNA_MRD
Characteristic Included
N = 62
1
Excluded
N = 20
1
p-value2
Age 66 (34 - 86) 70 (44 - 82) 0.8
Gender

>0.9
    Male 39 (63%) 12 (60%)
    Female 23 (37%) 8 (40%)
PrimSite

>0.9
    Stomach 38 (61%) 16 (80%)
    G/J 24 (39%) 4 (20%)
    Oesophagus 0 (0%) 0 (0%)
NAC

>0.9
    Neoadjuvant Therapy 55 (89%) 19 (95%)
    Upfront Surgery 7 (11%) 1 (5.0%)
NAC.Regimen

>0.9
     7 (11%) 1 (5.0%)
    Chemoimmunotherapy 7 (11%) 1 (5.0%)
    Chemotherapy 47 (76%) 18 (90%)
    Radiotherapy 1 (1.6%) 0 (0%)
TRG.Mandard

>0.9
    TRG1 3 (5.5%) 1 (5.9%)
    TRG2 8 (15%) 6 (35%)
    TRG3 21 (38%) 5 (29%)
    TRG4 16 (29%) 3 (18%)
    TRG5 7 (13%) 2 (12%)
    Unknown 7 3
TNM

>0.9
    T0-TisN0M0 3 (4.8%) 0 (0%)
    T1-T2N0 16 (26%) 9 (45%)
    T2-T3N0-N1 17 (27%) 4 (20%)
    T2N1-N2 2 (3.2%) 2 (10%)
    T3N2-N3 8 (13%) 1 (5.0%)
    T4N0-N1 9 (15%) 3 (15%)
    T4N2-N3 7 (11%) 1 (5.0%)
Stage

>0.9
    0 3 (4.8%) 0 (0%)
    I 16 (26%) 9 (45%)
    II 26 (42%) 7 (35%)
    III 17 (27%) 4 (20%)
Grade

>0.9
    G1 11 (28%) 3 (21%)
    G2 21 (53%) 6 (43%)
    G3 8 (20%) 5 (36%)
    Unknown 22 6
Lauren.Class

>0.9
     5 (8.1%) 3 (15%)
    Diffuse 18 (29%) 3 (15%)
    Intestinal 34 (55%) 11 (55%)
    Mixed 5 (8.1%) 3 (15%)
Margins

0.7
    R0 61 (98%) 17 (85%)
    R1 1 (1.6%) 3 (15%)
ACT

>0.9
    Adjuvant Treatment 53 (85%) 15 (75%)
    Observation 9 (15%) 5 (25%)
ACT.Regimen

0.2
     9 (15%) 10 (50%)
    Chemoimmunotherapy 4 (6.5%) 0 (0%)
    Chemotherapy 48 (77%) 10 (50%)
    Immunotherapy 1 (1.6%) 0 (0%)
DFS.Event

>0.9
    Recurrence 29 (47%) 8 (40%)
    No Recurrence 33 (53%) 12 (60%)
OS.Event

>0.9
    Deceased 19 (31%) 6 (30%)
    Alive 43 (69%) 14 (70%)
FU.months 29 (2 - 93) 34 (7 - 68) >0.9
1 Median (Min - Max); n (%)
2 Wilcoxon rank sum test; Fisher’s exact test

merged_table <- tbl_merge(tbls=list(Overall, ByctDNA_MRD))
merged_table
Characteristic
Table 1
Table 2
N = 821 Included
N = 62
1
Excluded
N = 20
1
p-value2
Age 67 (34 - 86) 66 (34 - 86) 70 (44 - 82) 0.8
Gender


>0.9
    Male 51 (62%) 39 (63%) 12 (60%)
    Female 31 (38%) 23 (37%) 8 (40%)
PrimSite


>0.9
    Stomach 54 (66%) 38 (61%) 16 (80%)
    G/J 28 (34%) 24 (39%) 4 (20%)
    Oesophagus 0 (0%) 0 (0%) 0 (0%)
NAC


>0.9
    Neoadjuvant Therapy 74 (90%) 55 (89%) 19 (95%)
    Upfront Surgery 8 (9.8%) 7 (11%) 1 (5.0%)
NAC.Regimen


>0.9
     8 (9.8%) 7 (11%) 1 (5.0%)
    Chemoimmunotherapy 8 (9.8%) 7 (11%) 1 (5.0%)
    Chemotherapy 65 (79%) 47 (76%) 18 (90%)
    Radiotherapy 1 (1.2%) 1 (1.6%) 0 (0%)
TRG.Mandard


>0.9
    TRG1 4 (5.6%) 3 (5.5%) 1 (5.9%)
    TRG2 14 (19%) 8 (15%) 6 (35%)
    TRG3 26 (36%) 21 (38%) 5 (29%)
    TRG4 19 (26%) 16 (29%) 3 (18%)
    TRG5 9 (13%) 7 (13%) 2 (12%)
    Unknown 10 7 3
TNM


>0.9
    T0-TisN0M0 3 (3.7%) 3 (4.8%) 0 (0%)
    T1-T2N0 25 (30%) 16 (26%) 9 (45%)
    T2-T3N0-N1 21 (26%) 17 (27%) 4 (20%)
    T2N1-N2 4 (4.9%) 2 (3.2%) 2 (10%)
    T3N2-N3 9 (11%) 8 (13%) 1 (5.0%)
    T4N0-N1 12 (15%) 9 (15%) 3 (15%)
    T4N2-N3 8 (9.8%) 7 (11%) 1 (5.0%)
Stage


>0.9
    0 3 (3.7%) 3 (4.8%) 0 (0%)
    I 25 (30%) 16 (26%) 9 (45%)
    II 33 (40%) 26 (42%) 7 (35%)
    III 21 (26%) 17 (27%) 4 (20%)
Grade


>0.9
    G1 14 (26%) 11 (28%) 3 (21%)
    G2 27 (50%) 21 (53%) 6 (43%)
    G3 13 (24%) 8 (20%) 5 (36%)
    Unknown 28 22 6
Lauren.Class


>0.9
     8 (9.8%) 5 (8.1%) 3 (15%)
    Diffuse 21 (26%) 18 (29%) 3 (15%)
    Intestinal 45 (55%) 34 (55%) 11 (55%)
    Mixed 8 (9.8%) 5 (8.1%) 3 (15%)
Margins


0.7
    R0 78 (95%) 61 (98%) 17 (85%)
    R1 4 (4.9%) 1 (1.6%) 3 (15%)
ACT


>0.9
    Adjuvant Treatment 68 (83%) 53 (85%) 15 (75%)
    Observation 14 (17%) 9 (15%) 5 (25%)
ACT.Regimen


0.2
     19 (23%) 9 (15%) 10 (50%)
    Chemoimmunotherapy 4 (4.9%) 4 (6.5%) 0 (0%)
    Chemotherapy 58 (71%) 48 (77%) 10 (50%)
    Immunotherapy 1 (1.2%) 1 (1.6%) 0 (0%)
DFS.Event


>0.9
    Recurrence 37 (45%) 29 (47%) 8 (40%)
    No Recurrence 45 (55%) 33 (53%) 12 (60%)
OS.Event


>0.9
    Deceased 25 (30%) 19 (31%) 6 (30%)
    Alive 57 (70%) 43 (69%) 14 (70%)
FU.months 32 (2 - 93) 29 (2 - 93) 34 (7 - 68) >0.9
1 Median (Min - Max); n (%)
2 Wilcoxon rank sum test; Fisher’s exact test

fit1 <- as_flex_table(
  merged_table,
  include = everything(),
  return_calls = FALSE)
fit1

Table 1

Table 2

Characteristic

N = 821

Included
N = 621

Excluded
N = 201

p-value2

Age

67 (34 - 86)

66 (34 - 86)

70 (44 - 82)

0.8

Gender

>0.9

Male

51 (62%)

39 (63%)

12 (60%)

Female

31 (38%)

23 (37%)

8 (40%)

PrimSite

>0.9

Stomach

54 (66%)

38 (61%)

16 (80%)

G/J

28 (34%)

24 (39%)

4 (20%)

Oesophagus

0 (0%)

0 (0%)

0 (0%)

NAC

>0.9

Neoadjuvant Therapy

74 (90%)

55 (89%)

19 (95%)

Upfront Surgery

8 (9.8%)

7 (11%)

1 (5.0%)

NAC.Regimen

>0.9

8 (9.8%)

7 (11%)

1 (5.0%)

Chemoimmunotherapy

8 (9.8%)

7 (11%)

1 (5.0%)

Chemotherapy

65 (79%)

47 (76%)

18 (90%)

Radiotherapy

1 (1.2%)

1 (1.6%)

0 (0%)

TRG.Mandard

>0.9

TRG1

4 (5.6%)

3 (5.5%)

1 (5.9%)

TRG2

14 (19%)

8 (15%)

6 (35%)

TRG3

26 (36%)

21 (38%)

5 (29%)

TRG4

19 (26%)

16 (29%)

3 (18%)

TRG5

9 (13%)

7 (13%)

2 (12%)

Unknown

10

7

3

TNM

>0.9

T0-TisN0M0

3 (3.7%)

3 (4.8%)

0 (0%)

T1-T2N0

25 (30%)

16 (26%)

9 (45%)

T2-T3N0-N1

21 (26%)

17 (27%)

4 (20%)

T2N1-N2

4 (4.9%)

2 (3.2%)

2 (10%)

T3N2-N3

9 (11%)

8 (13%)

1 (5.0%)

T4N0-N1

12 (15%)

9 (15%)

3 (15%)

T4N2-N3

8 (9.8%)

7 (11%)

1 (5.0%)

Stage

>0.9

0

3 (3.7%)

3 (4.8%)

0 (0%)

I

25 (30%)

16 (26%)

9 (45%)

II

33 (40%)

26 (42%)

7 (35%)

III

21 (26%)

17 (27%)

4 (20%)

Grade

>0.9

G1

14 (26%)

11 (28%)

3 (21%)

G2

27 (50%)

21 (53%)

6 (43%)

G3

13 (24%)

8 (20%)

5 (36%)

Unknown

28

22

6

Lauren.Class

>0.9

8 (9.8%)

5 (8.1%)

3 (15%)

Diffuse

21 (26%)

18 (29%)

3 (15%)

Intestinal

45 (55%)

34 (55%)

11 (55%)

Mixed

8 (9.8%)

5 (8.1%)

3 (15%)

Margins

0.7

R0

78 (95%)

61 (98%)

17 (85%)

R1

4 (4.9%)

1 (1.6%)

3 (15%)

ACT

>0.9

Adjuvant Treatment

68 (83%)

53 (85%)

15 (75%)

Observation

14 (17%)

9 (15%)

5 (25%)

ACT.Regimen

0.2

19 (23%)

9 (15%)

10 (50%)

Chemoimmunotherapy

4 (4.9%)

4 (6.5%)

0 (0%)

Chemotherapy

58 (71%)

48 (77%)

10 (50%)

Immunotherapy

1 (1.2%)

1 (1.6%)

0 (0%)

DFS.Event

>0.9

Recurrence

37 (45%)

29 (47%)

8 (40%)

No Recurrence

45 (55%)

33 (53%)

12 (60%)

OS.Event

>0.9

Deceased

25 (30%)

19 (31%)

6 (30%)

Alive

57 (70%)

43 (69%)

14 (70%)

FU.months

32 (2 - 93)

29 (2 - 93)

34 (7 - 68)

>0.9

1Median (Min - Max); n (%)

2Wilcoxon rank sum test; Fisher's exact test

save_as_docx(fit1, path= "~/Downloads/merged_table.docx")

#RFS by inclusion status

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~Included, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    Included, data = circ_data)

                n events median 0.95LCL 0.95UCL
Included=FALSE 20      8   52.0    31.4      NA
Included=TRUE  62     29   42.1    18.6      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ Included, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - Inclusion status", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("Included", "Excluded"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ Included, data = circ_data, conf.int = 0.95, 
    conf.type = "log-log")

                Included=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000       12.000        5.000        0.718        0.107        0.449        0.872 

                Included=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      26.0000      27.0000       0.5396       0.0661       0.4024       0.6582 
circ_data$Included <- factor(circ_data$Included, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ Included, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ Included, data = circ_data)

  n= 82, number of events= 37 

                 coef exp(coef) se(coef)      z Pr(>|z|)
IncludedFALSE -0.2622    0.7693   0.3998 -0.656    0.512

              exp(coef) exp(-coef) lower .95 upper .95
IncludedFALSE    0.7693        1.3    0.3514     1.684

Concordance= 0.546  (se = 0.031 )
Likelihood ratio test= 0.45  on 1 df,   p=0.5
Wald test            = 0.43  on 1 df,   p=0.5
Score (logrank) test = 0.43  on 1 df,   p=0.5
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 0.77 (0.35-1.68); p = 0.512"

#OS by inclusion status

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~Included, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    Included, data = circ_data)

                n events median 0.95LCL 0.95UCL
Included=FALSE 20      6     NA    37.4      NA
Included=TRUE  62     19     NA    52.7      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ Included, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - Inclusion status", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("Included", "Excluded"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ Included, data = circ_data, conf.int = 0.95, 
    conf.type = "log-log")

                Included=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      15.0000       3.0000       0.8382       0.0858       0.5770       0.9450 

                Included=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      34.0000      14.0000       0.7568       0.0572       0.6225       0.8489 
circ_data$Included <- factor(circ_data$Included, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ Included, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ Included, data = circ_data)

  n= 82, number of events= 25 

                  coef exp(coef) se(coef)      z Pr(>|z|)
IncludedFALSE -0.09663   0.90789  0.46937 -0.206    0.837

              exp(coef) exp(-coef) lower .95 upper .95
IncludedFALSE    0.9079      1.101    0.3618     2.278

Concordance= 0.524  (se = 0.041 )
Likelihood ratio test= 0.04  on 1 df,   p=0.8
Wald test            = 0.04  on 1 df,   p=0.8
Score (logrank) test = 0.04  on 1 df,   p=0.8
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 0.91 (0.36-2.28); p = 0.837"

#Heatmap with Clinical & Genomics Factors

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data %>% arrange(Stage)
circ_datadf <- as.data.frame(circ_data)

ha <- HeatmapAnnotation(
  Stage = circ_data$Stage,
  Gender = circ_data$Gender,
  PrimSite = circ_data$PrimSite,
  NAC = circ_data$NAC,
  ACT = circ_data$ACT,
  ctDNA.Base = circ_data$ctDNA.Base,
  ctDNA.C2D1 = circ_data$ctDNA.C2D1,
  ctDNA.postNAC = circ_data$ctDNA.postNAC,
  ctDNA.MRD = circ_data$ctDNA.MRD,
  ctDNA.surveillance = circ_data$ctDNA.surveillance,
  DFS.Event = circ_data$DFS.Event,
  OS.Event = circ_data$OS.Event,
  
  col = list(Stage = c("0" = "seagreen1", "I" = "seagreen1", "II" = "orange", "III" = "purple"),
    Gender = c("Female" = "goldenrod" , "Male" = "blue4"),
    PrimSite = c("Stomach" = "brown", "G/J" = "darkgreen", "Oesophagus" = "orange4"),
    NAC = c("FALSE" = "cornflowerblue", "TRUE" ="darkmagenta"),
    ACT = c("TRUE" = "brown4", "FALSE" ="khaki"),
    ctDNA.Base = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.C2D1 = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.postNAC = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.MRD = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.surveillance = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    DFS.Event = c("TRUE" = "red3", "FALSE" ="blue"),
    OS.Event = c("TRUE" = "black", "FALSE" ="gray")
)
)
ht <- Heatmap(matrix(nrow = 0, ncol = length(circ_data$Stage)),show_row_names = FALSE,cluster_rows = F,cluster_columns = FALSE, top_annotation = ha)
pdf("heatmap.pdf",width = 7, height = 7)
draw(ht, annotation_legend_side = "bottom")
dev.off()

#Overview Plot

setwd("~/Downloads") 
clinstage<- read.csv("PLAGAST_OP.csv")
clinstage_df<- as.data.frame(clinstage)

#Display the swimmer plot with the label box
oplot<-swimmer_plot(df=clinstage_df,
                    id='PatientName',
                    end='fu.diff.months',
                    fill='gray',
                    width=.01,)
oplot <- oplot + theme(panel.border = element_blank())
oplot <- oplot + scale_y_continuous(breaks = seq(-12, 96, by = 6))
oplot <- oplot + labs(x ="Patients" , y="Months from Surgery")
oplot



##plot events
oplot_ev1 <- oplot + swimmer_points(df_points=clinstage_df,
                                    id='PatientName',
                                    time='date.diff.months',
                                    name_shape ='Event_type',
                                    name_col = 'Event',
                                    size=3.5,fill='black',
                                    #col='darkgreen'
)
oplot_ev1


#Shape customization to Event_type

oplot_ev1.1 <- oplot_ev1 + ggplot2::scale_shape_manual(name="Event_type",values=c(1,16,6,18,4),breaks=c('ctDNA_neg','ctDNA_pos','Imaging','Surgery','Death'))

oplot_ev1.1


#plot treatment

oplot_ev2 <- oplot_ev1.1 + swimmer_lines(df_lines=clinstage_df,
                                         id='PatientName',
                                         start='Tx_start.months',
                                         end='Tx_end.months',
                                         name_col='Tx_type',
                                         size=3.5,
                                         name_alpha = 1.0)
oplot_ev2 <- oplot_ev2 + guides(linetype = guide_legend(override.aes = list(size = 5, color = "black")))
oplot_ev2  



#colour customization
oplot_ev2.2 <- oplot_ev2 + ggplot2::scale_color_manual(name="Event",values=c( "purple","black","black", "lightblue", "green", "red", "blue","orange"))
oplot_ev2.2

#RFS by ctDNA at Baseline - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Base, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Base, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.Base=NEGATIVE 17      5     NA    42.1      NA
ctDNA.Base=POSITIVE 39     20   22.3    13.3      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Base, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA Baseline | All pts", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.Base, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Base=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000       11.000        4.000        0.756        0.106        0.473        0.901 

                ctDNA.Base=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      13.0000      19.0000       0.4772       0.0849       0.3057       0.6301 
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.Base, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Base, data = circ_data)

  n= 56, number of events= 25 

                     coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.BasePOSITIVE 0.9196    2.5082   0.5030 1.828   0.0675 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.BasePOSITIVE     2.508     0.3987    0.9359     6.722

Concordance= 0.604  (se = 0.041 )
Likelihood ratio test= 3.92  on 1 df,   p=0.05
Wald test            = 3.34  on 1 df,   p=0.07
Score (logrank) test = 3.58  on 1 df,   p=0.06
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.51 (0.94-6.72); p = 0.068"

#OS by ctDNA at Baseline - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Base, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Base, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.Base=NEGATIVE 17      4     NA    52.7      NA
ctDNA.Base=POSITIVE 39     13     NA    24.5      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Base, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA Baseline | All pts", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.Base, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Base=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      14.0000       1.0000       0.9412       0.0571       0.6502       0.9915 

                ctDNA.Base=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      17.0000      11.0000       0.6832       0.0809       0.4963       0.8129 
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.Base, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Base, data = circ_data)

  n= 56, number of events= 17 

                     coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.BasePOSITIVE 0.7361    2.0878   0.5781 1.273    0.203

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.BasePOSITIVE     2.088      0.479    0.6724     6.483

Concordance= 0.597  (se = 0.05 )
Likelihood ratio test= 1.81  on 1 df,   p=0.2
Wald test            = 1.62  on 1 df,   p=0.2
Score (logrank) test = 1.69  on 1 df,   p=0.2
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.09 (0.67-6.48); p = 0.203"

#RFS by ctDNA levels at Baseline based on AUC optimal MTM/ml level - ctDNA Baseline positive

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- circ_data[circ_data$ctDNA.Base=="POSITIVE",]
circ_datadf <- as.data.frame(circ_data)

#DFS.Event
circ_data <- circ_data[complete.cases(circ_data$DFS.Event, circ_data$ctDNA.Base.MTM),]
circ_data$ctDNA.Base.MTM <- as.numeric(circ_data$ctDNA.Base.MTM)
ROC <- roc(DFS.Event ~  ctDNA.Base.MTM, data = circ_data, ci = TRUE)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
p<-ggroc(ROC,
         aes = c("linetype"), color = "blue",  size = 1,
         legacy.axes = TRUE) +
  geom_abline(color = "dark grey", size = 0.5) +
  theme_classic()+
  ylab("Sensitivity") + theme(axis.title.x = element_text(color="black", size=14), axis.title.y = element_text(color="black", size=14),axis.text.x = element_text(colour = "black", size=14),axis.text.y = element_text(colour = "black",size=14),legend.title  = element_blank(),legend.text = element_text(size=14))
Warning: Ignoring unknown parameters: `aes`Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.
p


#AUC
AUC <- auc(ROC)
print(AUC)
Area under the curve: 0.6211
AUC_conf <- ci.auc(ROC)
print(AUC_conf)
95% CI: 0.4354-0.8067 (DeLong)
res.roc <- roc(circ_data$DFS.Event, circ_data$ctDNA.Base.MTM)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
plot.roc(res.roc, print.auc = TRUE, print.thres = "best")


rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- circ_data[circ_data$ctDNA.Base=="POSITIVE",]
circ_datadf <- as.data.frame(circ_data)

# Create a new variable based on these quartiles
circ_data$ctDNA.6mMTM.Q <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 1.085 ~ 1,
    ctDNA.Base.MTM >= 1.085 ~ 2
  ))

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 16      5     NA   26.32      NA
ctDNA.6mMTM.Q=2 23     15   14.5    7.79      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="RFS - ctDNA MTM/mL groups at Baseline", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<1.085", "MTM/mL≥1.085"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        8.000        4.000        0.731        0.117        0.427        0.891 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        5.000       15.000        0.309        0.103        0.129        0.510 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<1.085", "MTM/mL≥1.085"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 39, number of events= 20 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.6mMTM.QMTM/mL≥1.085 1.0492    2.8553   0.5217 2.011   0.0443 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥1.085     2.855     0.3502     1.027     7.939

Concordance= 0.617  (se = 0.056 )
Likelihood ratio test= 4.64  on 1 df,   p=0.03
Wald test            = 4.04  on 1 df,   p=0.04
Score (logrank) test = 4.4  on 1 df,   p=0.04
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.86 (1.03-7.94); p = 0.044"

#OS by ctDNA levels at Baseline based on AUC optimal MTM/mL level from RFS model - ctDNA Baseline positive

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- circ_data[circ_data$ctDNA.Base=="POSITIVE",]
circ_datadf <- as.data.frame(circ_data)

# Create a new variable based on these quartiles

circ_data$ctDNA.6mMTM.Q <- NA
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 1.085 ~ 1,
    ctDNA.Base.MTM >= 1.085 ~ 2
  ))

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 16      3     NA      NA      NA
ctDNA.6mMTM.Q=2 23     10     38    18.9      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA MTM/mL groups at Baseline", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<1.085", "MTM/mL≥1.085"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        9.000        3.000        0.804        0.102        0.506        0.932 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        8.000        8.000        0.598        0.115        0.342        0.781 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<1.085", "MTM/mL≥1.085"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 39, number of events= 13 

                            coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.6mMTM.QMTM/mL≥1.085 0.9680    2.6326   0.6668 1.452    0.147

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥1.085     2.633     0.3798    0.7125     9.727

Concordance= 0.566  (se = 0.076 )
Likelihood ratio test= 2.43  on 1 df,   p=0.1
Wald test            = 2.11  on 1 df,   p=0.1
Score (logrank) test = 2.26  on 1 df,   p=0.1
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.63 (0.71-9.73); p = 0.147"

#RFS by ctDNA at Baseline - excluding pts that did not receive NAC

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$NAC==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Base, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Base, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.Base=NEGATIVE 16      5     NA    42.1      NA
ctDNA.Base=POSITIVE 35     17   26.3    14.5      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Base, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA Baseline | NAC treated only", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.Base, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Base=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000       10.000        4.000        0.740        0.112        0.446        0.894 

                ctDNA.Base=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      12.0000      16.0000       0.5096       0.0893       0.3256       0.6670 
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.Base, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Base, data = circ_data)

  n= 51, number of events= 22 

                     coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.BasePOSITIVE 0.8020    2.2300   0.5121 1.566    0.117

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.BasePOSITIVE      2.23     0.4484    0.8173     6.085

Concordance= 0.599  (se = 0.044 )
Likelihood ratio test= 2.78  on 1 df,   p=0.1
Wald test            = 2.45  on 1 df,   p=0.1
Score (logrank) test = 2.58  on 1 df,   p=0.1
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.23 (0.82-6.08); p = 0.117"

#OS by ctDNA at Baseline - excluding pts that did not receive NAC

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$NAC==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Base, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Base, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.Base=NEGATIVE 16      4     NA    52.7      NA
ctDNA.Base=POSITIVE 35     11     NA    24.5      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Base, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA Baseline | NAC treated only", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.Base, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Base=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      13.0000       1.0000       0.9375       0.0605       0.6323       0.9910 

                ctDNA.Base=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      15.0000       9.0000       0.7040       0.0854       0.5012       0.8367 
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.Base, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Base, data = circ_data)

  n= 51, number of events= 15 

                     coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.BasePOSITIVE 0.6136    1.8470   0.5897 1.041    0.298

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.BasePOSITIVE     1.847     0.5414    0.5815     5.867

Concordance= 0.59  (se = 0.055 )
Likelihood ratio test= 1.17  on 1 df,   p=0.3
Wald test            = 1.08  on 1 df,   p=0.3
Score (logrank) test = 1.12  on 1 df,   p=0.3
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1.85 (0.58-5.87); p = 0.298"

#RFS by ctDNA levels at Baseline based on AUC optimal MTM/ml level - ctDNA Baseline positive excluding pts that did not receive NAC

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$NAC==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- circ_data[circ_data$ctDNA.Base=="POSITIVE",]
circ_datadf <- as.data.frame(circ_data)

#DFS.Event
circ_data <- circ_data[complete.cases(circ_data$DFS.Event, circ_data$ctDNA.Base.MTM),]
circ_data$ctDNA.Base.MTM <- as.numeric(circ_data$ctDNA.Base.MTM)
ROC <- roc(DFS.Event ~  ctDNA.Base.MTM, data = circ_data, ci = TRUE)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
p<-ggroc(ROC,
         aes = c("linetype"), color = "blue",  size = 1,
         legacy.axes = TRUE) +
  geom_abline(color = "dark grey", size = 0.5) +
  theme_classic()+
  ylab("Sensitivity") + theme(axis.title.x = element_text(color="black", size=14), axis.title.y = element_text(color="black", size=14),axis.text.x = element_text(colour = "black", size=14),axis.text.y = element_text(colour = "black",size=14),legend.title  = element_blank(),legend.text = element_text(size=14))
Warning: Ignoring unknown parameters: `aes`
p


#AUC
AUC <- auc(ROC)
print(AUC)
Area under the curve: 0.6373
AUC_conf <- ci.auc(ROC)
print(AUC_conf)
95% CI: 0.4424-0.8321 (DeLong)
res.roc <- roc(circ_data$DFS.Event, circ_data$ctDNA.Base.MTM)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
plot.roc(res.roc, print.auc = TRUE, print.thres = "best")


rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$NAC==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- circ_data[circ_data$ctDNA.Base=="POSITIVE",]
circ_datadf <- as.data.frame(circ_data)

# Create a new variable based on these quartiles
circ_data$ctDNA.6mMTM.Q <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 0.71 ~ 1,
    ctDNA.Base.MTM >= 0.71 ~ 2
  ))

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 11      2     NA      NA      NA
ctDNA.6mMTM.Q=2 24     15   14.5    7.79      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="RFS - ctDNA MTM/mL groups at Baseline", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<0.71", "MTM/mL≥0.71"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       6.0000       1.0000       0.9091       0.0867       0.5081       0.9867 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000       15.000        0.340        0.102        0.156        0.535 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<0.71", "MTM/mL≥0.71"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 35, number of events= 17 

                           coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.6mMTM.QMTM/mL≥0.71 1.5274    4.6061   0.7556 2.021   0.0432 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                         exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥0.71     4.606     0.2171     1.048     20.25

Concordance= 0.632  (se = 0.056 )
Likelihood ratio test= 5.83  on 1 df,   p=0.02
Wald test            = 4.09  on 1 df,   p=0.04
Score (logrank) test = 4.92  on 1 df,   p=0.03
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 4.61 (1.05-20.25); p = 0.043"

#RFS by ctDNA on-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.C2D1!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.C2D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.C2D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C2D1=NEGATIVE 20      4     NA      NA      NA
ctDNA.C2D1=POSITIVE 21     14   13.3    6.57      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA status on-NAT | All pts", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      14.0000       3.0000       0.8400       0.0853       0.5792       0.9459 

                ctDNA.C2D1=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        4.000       13.000        0.342        0.109        0.146        0.550 
circ_data$ctDNA.C2D1 <- factor(circ_data$ctDNA.C2D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1, data = circ_data)

  n= 41, number of events= 18 

                     coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.C2D1POSITIVE 1.8205    6.1750   0.5767 3.157   0.0016 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1POSITIVE     6.175     0.1619     1.994     19.12

Concordance= 0.718  (se = 0.046 )
Likelihood ratio test= 12.42  on 1 df,   p=4e-04
Wald test            = 9.97  on 1 df,   p=0.002
Score (logrank) test = 12.64  on 1 df,   p=4e-04
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 6.17 (1.99-19.12); p = 0.002"

#OS by ctDNA on-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.C2D1!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.C2D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.C2D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C2D1=NEGATIVE 20      3     NA      NA      NA
ctDNA.C2D1=POSITIVE 21      9   24.5    14.4      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA status on-NAT | All pts", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      15.0000       1.0000       0.9500       0.0487       0.6947       0.9928 

                ctDNA.C2D1=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        8.000        0.586        0.114        0.335        0.771 
circ_data$ctDNA.C2D1 <- factor(circ_data$ctDNA.C2D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1, data = circ_data)

  n= 41, number of events= 12 

                     coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.C2D1POSITIVE 1.5506    4.7145   0.6795 2.282   0.0225 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1POSITIVE     4.714     0.2121     1.245     17.86

Concordance= 0.706  (se = 0.054 )
Likelihood ratio test= 6.18  on 1 df,   p=0.01
Wald test            = 5.21  on 1 df,   p=0.02
Score (logrank) test = 6.2  on 1 df,   p=0.01
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 4.71 (1.24-17.86); p = 0.022"

#DFS by ctDNA Clearance during NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 20     13   13.3    7.36      NA
ctDNA.C2D1.Clearance=TRUE   9      2     NA   18.20      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="RFS - ctDNA clearance C2D1", ylab= "Recurrence-Free Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        4.000       12.000        0.359        0.114        0.153        0.572 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        5.000        2.000        0.741        0.161        0.289        0.930 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 29, number of events= 15 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.C2D1.ClearanceFALSE 1.6403    5.1567   0.7649 2.144    0.032 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     5.157     0.1939     1.152     23.09

Concordance= 0.667  (se = 0.046 )
Likelihood ratio test= 6.5  on 1 df,   p=0.01
Wald test            = 4.6  on 1 df,   p=0.03
Score (logrank) test = 5.66  on 1 df,   p=0.02
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.16 (1.15-23.09); p = 0.032"

#OS by ctDNA Clearance during NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 20      8     NA    18.9      NA
ctDNA.C2D1.Clearance=TRUE   9      1     NA    38.0      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="OS - ctDNA clearance C2D1", ylab= "Overall Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        7.000        0.616        0.116        0.353        0.798 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
          24            6            0            1            0           NA           NA 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 29, number of events= 9 

                           coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.C2D1.ClearanceFALSE 1.634     5.126    1.064 1.536    0.125

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     5.126     0.1951    0.6369     41.25

Concordance= 0.669  (se = 0.047 )
Likelihood ratio test= 3.48  on 1 df,   p=0.06
Wald test            = 2.36  on 1 df,   p=0.1
Score (logrank) test = 2.92  on 1 df,   p=0.09
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.13 (0.64-41.25); p = 0.125"

#RFS by ctDNA post-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.postNAC, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.postNAC, data = circ_data)

                        n events median 0.95LCL 0.95UCL
ctDNA.postNAC=NEGATIVE 30     10     NA   21.52      NA
ctDNA.postNAC=POSITIVE 11      8   7.79    3.55      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.postNAC, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA status post-NAT | All pts", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.postNAC, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.postNAC=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      13.0000      10.0000       0.6377       0.0933       0.4269       0.7883 

                ctDNA.postNAC=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
    24.00000      1.00000      8.00000      0.13636      0.12392      0.00767      0.44263 
circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.postNAC, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.postNAC, data = circ_data)

  n= 41, number of events= 18 

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.postNACPOSITIVE 1.6603    5.2610   0.5036 3.297 0.000978 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                      exp(coef) exp(-coef) lower .95 upper .95
ctDNA.postNACPOSITIVE     5.261     0.1901     1.961     14.12

Concordance= 0.669  (se = 0.052 )
Likelihood ratio test= 9.69  on 1 df,   p=0.002
Wald test            = 10.87  on 1 df,   p=0.001
Score (logrank) test = 13.08  on 1 df,   p=3e-04
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.26 (1.96-14.12); p = 0.001"

#OS by ctDNA post-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.postNAC, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.postNAC, data = circ_data)

                        n events median 0.95LCL 0.95UCL
ctDNA.postNAC=NEGATIVE 30      5     NA      NA      NA
ctDNA.postNAC=POSITIVE 11      8   18.9    11.7      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.postNAC, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA status post-NAT | All pts", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.postNAC, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.postNAC=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      16.0000       3.0000       0.9000       0.0548       0.7212       0.9666 

                ctDNA.postNAC=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       2.0000       7.0000       0.2273       0.1409       0.0346       0.5207 
circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.postNAC, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.postNAC, data = circ_data)

  n= 41, number of events= 13 

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.postNACPOSITIVE 1.9944    7.3479   0.5811 3.432 0.000599 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                      exp(coef) exp(-coef) lower .95 upper .95
ctDNA.postNACPOSITIVE     7.348     0.1361     2.352     22.95

Concordance= 0.711  (se = 0.07 )
Likelihood ratio test= 11.82  on 1 df,   p=6e-04
Wald test            = 11.78  on 1 df,   p=6e-04
Score (logrank) test = 15.82  on 1 df,   p=7e-05
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 7.35 (2.35-22.95); p = 0.001"

#Multivariate cox regression for RFS - ctDNA post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("Stomach","G/J"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$pT.Stage <- factor(circ_data$pT.Stage, levels=c("T1-T3","T4"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
circ_data$ACT <- factor(circ_data$ACT, levels=c("TRUE","FALSE"), labels = c("Yes", "No"))
surv_object <- Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.postNAC + PrimSite + Gender + Age.Group + ACT, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for RFS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#Multivariate cox regression for OS - ctDNA post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("Stomach","G/J"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$pT.Stage <- factor(circ_data$pT.Stage, levels=c("T1-T3","T4"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
circ_data$ACT <- factor(circ_data$ACT, levels=c("TRUE","FALSE"), labels = c("Yes", "No"))
surv_object <- Surv(time = circ_data$FU.months, event = circ_data$OS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.postNAC + PrimSite + Gender + Age.Group + ACT, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for OS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#RFS by ctDNA Clearance post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      6     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5   9.63    6.21      NA
ctDNA.Stage.II.TNM=3  5      4   7.36    2.53      NA
ctDNA.Stage.II.TNM=4  3      3   3.55    1.35      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA post-NAT & ypTN", ylab= "Disease-Free Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     25       0    1.000  0.0000        1.000        1.000
   24     13       6    0.733  0.0944        0.497        0.872

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000         1.00        1.000
   24      1       5    0.208   0.179         0.01        0.586

                ctDNA.Stage.II.TNM=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  1.9291    6.8836   0.6303 3.061  0.00221 ** 
ctDNA.Stage.II.TNMctDNA(-) & T4     2.2440    9.4313   0.6932 3.237  0.00121 ** 
ctDNA.Stage.II.TNMctDNA(+) & T4     3.2728   26.3857   0.8116 4.032 5.52e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3     6.884     0.1453     2.001     23.68
ctDNA.Stage.II.TNMctDNA(-) & T4        9.431     0.1060     2.424     36.70
ctDNA.Stage.II.TNMctDNA(+) & T4       26.386     0.0379     5.376    129.49

Concordance= 0.775  (se = 0.043 )
Likelihood ratio test= 20.62  on 3 df,   p=1e-04
Wald test            = 19.79  on 3 df,   p=2e-04
Score (logrank) test = 29.52  on 3 df,   p=2e-06
#Repeat analysis to compare ctDNA post-NAT (+) T1-T3 vs T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      6     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5   9.63    6.21      NA
ctDNA.Stage.II.TNM=3  5      4   7.36    2.53      NA
ctDNA.Stage.II.TNM=4  3      3   3.55    1.35      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                       coef exp(coef) se(coef)      z Pr(>|z|)   
ctDNA.Stage.II.TNM4  1.3437    3.8331   0.7683  1.749  0.08031 . 
ctDNA.Stage.II.TNM1 -1.9291    0.1453   0.6303 -3.061  0.00221 **
ctDNA.Stage.II.TNM3  0.3149    1.3701   0.6866  0.459  0.64652   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4    3.8331     0.2609   0.85028   17.2799
ctDNA.Stage.II.TNM1    0.1453     6.8836   0.04224    0.4997
ctDNA.Stage.II.TNM3    1.3701     0.7299   0.35669    5.2629

Concordance= 0.775  (se = 0.043 )
Likelihood ratio test= 20.62  on 3 df,   p=1e-04
Wald test            = 19.79  on 3 df,   p=2e-04
Score (logrank) test = 29.52  on 3 df,   p=2e-06

#OS by ctDNA Clearance post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5  16.66   11.66      NA
ctDNA.Stage.II.TNM=3  5      3   8.31    3.58      NA
ctDNA.Stage.II.TNM=4  3      3  19.09    2.40      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA post-NAT & ypTN", ylab= "Overall Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     25       0        1       0            1            1
   24     16       0        1       0           NA           NA

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000       1.0000        1.000
   24      2       4    0.333   0.192       0.0461        0.676

                ctDNA.Stage.II.TNM=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  2.7833   16.1727   0.8451 3.293 0.000990 ***
ctDNA.Stage.II.TNMctDNA(-) & T4     3.6483   38.4083   1.0196 3.578 0.000346 ***
ctDNA.Stage.II.TNMctDNA(+) & T4     3.6058   36.8115   0.9977 3.614 0.000302 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3     16.17    0.06183     3.086     84.75
ctDNA.Stage.II.TNMctDNA(-) & T4        38.41    0.02604     5.207    283.33
ctDNA.Stage.II.TNMctDNA(+) & T4        36.81    0.02717     5.208    260.17

Concordance= 0.863  (se = 0.035 )
Likelihood ratio test= 24.39  on 3 df,   p=2e-05
Wald test            = 16.23  on 3 df,   p=0.001
Score (logrank) test = 30.45  on 3 df,   p=1e-06
#Repeat analysis to compare ctDNA post-NAT (+) T1-T3 vs T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5  16.66   11.66      NA
ctDNA.Stage.II.TNM=3  5      3   8.31    3.58      NA
ctDNA.Stage.II.TNM=4  3      3  19.09    2.40      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                        coef exp(coef) se(coef)      z Pr(>|z|)    
ctDNA.Stage.II.TNM4  0.82248   2.27615  0.79900  1.029  0.30329    
ctDNA.Stage.II.TNM1 -2.78333   0.06183  0.84513 -3.293  0.00099 ***
ctDNA.Stage.II.TNM3  0.86495   2.37489  0.80811  1.070  0.28447    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   2.27615     0.4393    0.4754    10.897
ctDNA.Stage.II.TNM1   0.06183    16.1727    0.0118     0.324
ctDNA.Stage.II.TNM3   2.37489     0.4211    0.4873    11.575

Concordance= 0.863  (se = 0.035 )
Likelihood ratio test= 24.39  on 3 df,   p=2e-05
Wald test            = 16.23  on 3 df,   p=0.001
Score (logrank) test = 30.45  on 3 df,   p=1e-06

#Association of ctDNA Dynamics post-NAT and Response

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 16      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  3      1     NA    3.55      NA
ctDNA.Stage.II.TNM=3 14      8   18.2   11.40      NA
ctDNA.Stage.II.TNM=4  8      7    7.0    2.56      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA post-NAT & ypN", ylab= "Disease-Free Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000  0.0000        1.000        1.000
   24     12       2    0.875  0.0827        0.586        0.967

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      3       0    1.000   0.000       1.0000        1.000
   24      1       1    0.667   0.272       0.0541        0.945

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     14       0    1.000    0.00       1.0000        1.000
   24      1       8    0.188    0.16       0.0107        0.539

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0  1.8009    6.0550   1.2294 1.465  0.14295    
ctDNA.Stage.II.TNMctDNA(-) & ypN+  2.3395   10.3756   0.8452 2.768  0.00564 ** 
ctDNA.Stage.II.TNMctDNA(+) & ypN+  3.7725   43.4875   0.9323 4.046  5.2e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0     6.055    0.16515    0.5441     67.38
ctDNA.Stage.II.TNMctDNA(-) & ypN+    10.376    0.09638    1.9794     54.39
ctDNA.Stage.II.TNMctDNA(+) & ypN+    43.488    0.02300    6.9948    270.37

Concordance= 0.773  (se = 0.058 )
Likelihood ratio test= 23.01  on 3 df,   p=4e-05
Wald test            = 17.09  on 3 df,   p=7e-04
Score (logrank) test = 26.38  on 3 df,   p=8e-06
#Repeat analysis to compare ctDNA post-NAT (-) vs (+) in ypN+
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 16      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  3      1     NA    3.55      NA
ctDNA.Stage.II.TNM=3 14      8   18.2   11.40      NA
ctDNA.Stage.II.TNM=4  8      7    7.0    2.56      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("3","4","1","2"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                        coef exp(coef) se(coef)      z Pr(>|z|)   
ctDNA.Stage.II.TNM4  1.43302   4.19133  0.57130  2.508  0.01213 * 
ctDNA.Stage.II.TNM1 -2.33945   0.09638  0.84525 -2.768  0.00564 **
ctDNA.Stage.II.TNM2 -0.53857   0.58358  1.08425 -0.497  0.61939   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   4.19133     0.2386   1.36791   12.8424
ctDNA.Stage.II.TNM1   0.09638    10.3756   0.01839    0.5052
ctDNA.Stage.II.TNM2   0.58358     1.7136   0.06969    4.8867

Concordance= 0.773  (se = 0.058 )
Likelihood ratio test= 23.01  on 3 df,   p=4e-05
Wald test            = 17.09  on 3 df,   p=7e-04
Score (logrank) test = 26.38  on 3 df,   p=8e-06

#Association of ctDNA Dynamics post-NAT and Response V2 (TRG1/2 vs TRG3-5)

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 16      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  3      1   19.1   19.09      NA
ctDNA.Stage.II.TNM=3 14      3     NA   24.25      NA
ctDNA.Stage.II.TNM=4  8      7   14.4    8.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA post-NAT & ypN", ylab= "Overall Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000  0.0000        1.000        1.000
   24     13       1    0.938  0.0605        0.632        0.991

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      3       0      1.0   0.000      1.00000         1.00
   24      1       1      0.5   0.354      0.00598         0.91

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     14       0    1.000  0.0000        1.000        1.000
   24      3       2    0.857  0.0935        0.539        0.962

                ctDNA.Stage.II.TNM=4 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000      1.00000        1.000
   24      1       6    0.146   0.135      0.00726        0.471
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0  1.4824    4.4036   1.2274 1.208 0.227138    
ctDNA.Stage.II.TNMctDNA(-) & ypN+  1.4115    4.1022   0.9495 1.487 0.137123    
ctDNA.Stage.II.TNMctDNA(+) & ypN+  3.1167   22.5721   0.8727 3.571 0.000355 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0     4.404     0.2271    0.3972     48.82
ctDNA.Stage.II.TNMctDNA(-) & ypN+     4.102     0.2438    0.6380     26.38
ctDNA.Stage.II.TNMctDNA(+) & ypN+    22.572     0.0443    4.0804    124.87

Concordance= 0.765  (se = 0.076 )
Likelihood ratio test= 16.79  on 3 df,   p=8e-04
Wald test            = 15.08  on 3 df,   p=0.002
Score (logrank) test = 23.63  on 3 df,   p=3e-05
#Repeat analysis to compare ctDNA post-NAT (+) ypN0 vs ypN+
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                        coef exp(coef) se(coef)      z Pr(>|z|)
ctDNA.Stage.II.TNM4  1.63430   5.12585  1.11292  1.468    0.142
ctDNA.Stage.II.TNM1 -1.48242   0.22709  1.22741 -1.208    0.227
ctDNA.Stage.II.TNM3 -0.07091   0.93155  1.17530 -0.060    0.952

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4    5.1259     0.1951   0.57869    45.403
ctDNA.Stage.II.TNM1    0.2271     4.4036   0.02048     2.517
ctDNA.Stage.II.TNM3    0.9315     1.0735   0.09306     9.325

Concordance= 0.765  (se = 0.076 )
Likelihood ratio test= 16.79  on 3 df,   p=8e-04
Wald test            = 15.08  on 3 df,   p=0.002
Score (logrank) test = 23.63  on 3 df,   p=3e-05

#RFS by ctDNA Dynamics post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 10      7   7.79    2.56      NA
ctDNA.C2D1.Clearance=TRUE  17      6     NA   18.20      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="RFS - ctDNA clearance post-NAT", ylab= "Recurrence-Free Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
    24.00000      1.00000      7.00000      0.15000      0.13555      0.00802      0.47435 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        6.000        0.613        0.128        0.324        0.809 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 27, number of events= 13 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.C2D1.ClearanceFALSE 1.4237    4.1523   0.5823 2.445   0.0145 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     4.152     0.2408     1.326        13

Concordance= 0.668  (se = 0.064 )
Likelihood ratio test= 5.82  on 1 df,   p=0.02
Wald test            = 5.98  on 1 df,   p=0.01
Score (logrank) test = 6.85  on 1 df,   p=0.009
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 4.15 (1.33-13); p = 0.014"

#OS by ctDNA Dynamics post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 10      7   18.9    11.7      NA
ctDNA.C2D1.Clearance=TRUE  17      2     NA      NA      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="OS - ctDNA clearance post-NAT", ylab= "Overall Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       2.0000       6.0000       0.2571       0.1560       0.0384       0.5679 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       6.0000       2.0000       0.8824       0.0781       0.6060       0.9692 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 27, number of events= 9 

                            coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.C2D1.ClearanceFALSE 2.0846    8.0411   0.8039 2.593  0.00951 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     8.041     0.1244     1.664     38.87

Concordance= 0.709  (se = 0.089 )
Likelihood ratio test= 8.55  on 1 df,   p=0.003
Wald test            = 6.72  on 1 df,   p=0.01
Score (logrank) test = 9.48  on 1 df,   p=0.002
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 8.04 (1.66-38.87); p = 0.01"

#Levels of Baseline MTM/mL in ctDNA Dynamics post-NAT categories

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

#Vertical Fisher plot for ctDNA clearance post-NAT and Rec Status
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

   40 observations deleted due to missingness 
                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      1     NA   18.20      NA
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-", "ctDNA +/+/-", "ctDNA +/+/+"))
circ_data$TRG <- factor(circ_data$TRG, levels = c("TRG1/2/3", "TRG4/5"))
contingency_table <- table(circ_data$ctDNA.Dynamics, circ_data$TRG)
fisher_exact_test <- fisher.test(contingency_table)
chi_square_test <- chisq.test(contingency_table)
Warning: Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test

data:  contingency_table
X-squared = 11.378, df = 2, p-value = 0.003383
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.002557
alternative hypothesis: two.sided
print(contingency_table)
             
              TRG1/2/3 TRG4/5
  ctDNA +/-/-        4      0
  ctDNA +/+/-        6      4
  ctDNA +/+/+        0      7
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2

# Swapping x and y in ggplot function to make bar plot vertical
ggplot(table_df, aes(y = Var1, x = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(x = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA Dymamics post-NAT", y = "ctDNA", x = "Patients (%)", fill = "Path Response") +
  scale_x_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("TRG1/2/3" = "lightblue3", "TRG4/5" = "red")) + # define custom colors
  theme(axis.text.y = element_text(angle = 0, hjust = 1.5, size = 14), # increase y-axis text size
        axis.text.x = element_text(size = 14, color = "black"), # increase x-axis text size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Recurrence label size


#Calculating p-value with Fisher exact test for the ctDNA +/+/+ vs ctDNA +/+/-
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

#Vertical Fisher plot for ctDNA clearance post-NAT and Rec Status
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="",]
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="ctDNA +/-/-",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

   40 observations deleted due to missingness 
                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/+/-", "ctDNA +/+/+"))
circ_data$TRG <- factor(circ_data$TRG, levels = c("TRG1/2/3", "TRG4/5"))
contingency_table <- table(circ_data$ctDNA.Dynamics, circ_data$TRG)
fisher_exact_test <- fisher.test(contingency_table)
chi_square_test <- chisq.test(contingency_table)
Warning: Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 4.1295, df = 1, p-value = 0.04214
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.0345
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 1.176016      Inf
sample estimates:
odds ratio 
       Inf 
print(contingency_table)
             
              TRG1/2/3 TRG4/5
  ctDNA +/+/-        6      4
  ctDNA +/+/+        0      7

#Time of ctDNA draws at the MRD window from surgery

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

#Vertical Fisher plot for ctDNA clearance post-NAT and Rec Status
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

   40 observations deleted due to missingness 
                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      1     NA   18.20      NA
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-", "ctDNA +/+/-", "ctDNA +/+/+"))
circ_data$TRGv2 <- factor(circ_data$TRGv2, levels = c("TRG1/2", "TRG3/4/5"))
contingency_table <- table(circ_data$ctDNA.Dynamics, circ_data$TRGv2)
fisher_exact_test <- fisher.test(contingency_table)
chi_square_test <- chisq.test(contingency_table)
Warning: Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test

data:  contingency_table
X-squared = 1.8083, df = 2, p-value = 0.4049
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.3947
alternative hypothesis: two.sided
print(contingency_table)
             
              TRG1/2 TRG3/4/5
  ctDNA +/-/-      1        3
  ctDNA +/+/-      2        8
  ctDNA +/+/+      0        7
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2

# Swapping x and y in ggplot function to make bar plot vertical
ggplot(table_df, aes(y = Var1, x = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(x = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA Dymamics post-NAT", y = "ctDNA", x = "Patients (%)", fill = "Path Response") +
  scale_x_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("TRG1/2" = "lightblue3", "TRG3/4/5" = "red")) + # define custom colors
  theme(axis.text.y = element_text(angle = 0, hjust = 1.5, size = 14), # increase y-axis text size
        axis.text.x = element_text(size = 14, color = "black"), # increase x-axis text size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Recurrence label size


#Calculating p-value with Fisher exact test for the ctDNA +/+/+ vs ctDNA +/+/-
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

#Vertical Fisher plot for ctDNA clearance post-NAT and Rec Status
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="",]
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="ctDNA +/-/-",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

   40 observations deleted due to missingness 
                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/+/-", "ctDNA +/+/+"))
circ_data$TRGv2 <- factor(circ_data$TRGv2, levels = c("TRG1/2", "TRG3/4/5"))
contingency_table <- table(circ_data$ctDNA.Dynamics, circ_data$TRGv2)
fisher_exact_test <- fisher.test(contingency_table)
chi_square_test <- chisq.test(contingency_table)
Warning: Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 0.24488, df = 1, p-value = 0.6207
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.4853
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.1311443       Inf
sample estimates:
odds ratio 
       Inf 
print(contingency_table)
             
              TRG1/2 TRG3/4/5
  ctDNA +/+/-      2        8
  ctDNA +/+/+      0        7

#RFS by ctDNA at the MRD Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.Dynamics),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      1     NA   18.20      NA
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Dynamics, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA Dynamics post-NAT", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Dynamics, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Dynamics=ctDNA +/-/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      5       0    1.000   0.000       1.0000        1.000
   24      2       1    0.667   0.272       0.0541        0.945

                ctDNA.Dynamics=ctDNA +/+/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0     1.00   0.000        1.000        1.000
   24      2       5     0.48   0.164        0.161        0.745

                ctDNA.Dynamics=ctDNA +/+/+ 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            7            0            1            0            1            1 
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"))
cox_fit <- coxph(surv_object ~ ctDNA.Dynamics, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Dynamics, data = circ_data)

  n= 22, number of events= 12 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.DynamicsctDNA +/+/-  1.343     3.831    1.100 1.221   0.2219  
ctDNA.DynamicsctDNA +/+/+  2.921    18.568    1.157 2.526   0.0116 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.DynamicsctDNA +/+/-     3.831    0.26100    0.4439     33.07
ctDNA.DynamicsctDNA +/+/+    18.568    0.05386    1.9237    179.22

Concordance= 0.756  (se = 0.053 )
Likelihood ratio test= 10.01  on 2 df,   p=0.007
Wald test            = 8.49  on 2 df,   p=0.01
Score (logrank) test = 11.47  on 2 df,   p=0.003

#OS by ctDNA at the MRD Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.Dynamics),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      0     NA      NA      NA
ctDNA.Dynamics=ctDNA +/+/- 10      2     NA      NA      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   14.4    8.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Dynamics, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="OS - ctDNA Dynamics post-NAT", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Dynamics, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Dynamics=ctDNA +/-/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      5       0        1       0            1            1
   24      2       0        1       0           NA           NA

                ctDNA.Dynamics=ctDNA +/+/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0      1.0   0.000        1.000        1.000
   24      2       2      0.8   0.126        0.409        0.946

                ctDNA.Dynamics=ctDNA +/+/+ 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      7       0    1.000   0.000      1.00000        1.000
   24      1       5    0.171   0.156      0.00794        0.526
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"))
cox_fit <- coxphf(surv_object ~ ctDNA.Dynamics, data=circ_data)
summary(cox_fit)
coxphf(formula = surv_object ~ ctDNA.Dynamics, data = circ_data)

Model fitted by Penalized ML
Confidence intervals and p-values by Profile Likelihood 

                              coef se(coef) exp(coef) lower 0.95 upper 0.95     Chisq           p
ctDNA.DynamicsctDNA +/+/- 1.178268 1.696304  3.248742  0.2627946    448.914 0.7281482 0.393484095
ctDNA.DynamicsctDNA +/+/+ 2.776185 1.609915 16.057642  1.8668569   2102.174 7.2774206 0.006982673

Likelihood ratio test=8.847995 on 2 df, p=0.01198622, n=22
Wald test = 5.979249 on 2 df, p = 0.05030632

Covariance-Matrix:
                          ctDNA.DynamicsctDNA +/+/- ctDNA.DynamicsctDNA +/+/+
ctDNA.DynamicsctDNA +/+/-                  2.877449                  2.403504
ctDNA.DynamicsctDNA +/+/+                  2.403504                  2.591825

#RFS by ctDNA at the MRD Window - ACT pts only

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- as.data.frame(circ_data)

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

# Transform ctDNA.Base.MTM with log10
circ_data <- subset(circ_data, !is.na(ctDNA.Dynamics))
circ_data$ctDNA.Base.MTM <- as.numeric(as.character(circ_data$ctDNA.Base.MTM))
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"))
median_Base_MTM <- aggregate(ctDNA.Base.MTM ~ ctDNA.Dynamics, data = circ_data, FUN = median)
print(median_Base_MTM)

# Create violin plot with log10 scale on y-axis
ggplot(circ_data, aes(x=ctDNA.Dynamics, y=ctDNA.Base.MTM, fill=ctDNA.Dynamics)) +
  geom_violin(trim=FALSE) +
  scale_fill_manual(values=c("ctDNA +/-/-"="lightblue", "ctDNA +/+/-"="lightgreen", "ctDNA +/+/+"="salmon")) +
  geom_boxplot(width=0.1, fill="white", colour="black", alpha=0.5) +
  scale_y_log10(breaks=c(0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000)) +
  labs(title="Baseline MTM/mL | Dynamics post-NAT", x="Dynamics post-NAT", y="Baseline MTM/mL") +
  theme_minimal() +
  theme(legend.position="none")

m3_1v2 <- wilcox.test(ctDNA.Base.MTM ~ ctDNA.Dynamics,
                      data = circ_data[circ_data$ctDNA.Dynamics %in% c("ctDNA +/-/-", "ctDNA +/+/-"), ],
                      na.rm = TRUE)
Warning: cannot compute exact p-value with ties
print(m3_1v2)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.Base.MTM by ctDNA.Dynamics
W = 26, p-value = 0.9511
alternative hypothesis: true location shift is not equal to 0
m3_1v3 <- wilcox.test(ctDNA.Base.MTM ~ ctDNA.Dynamics,
                      data = circ_data[circ_data$ctDNA.Dynamics %in% c("ctDNA +/-/-", "ctDNA +/+/+"), ],
                      na.rm = TRUE)
print(m3_1v3)

    Wilcoxon rank sum exact test

data:  ctDNA.Base.MTM by ctDNA.Dynamics
W = 7, p-value = 0.1061
alternative hypothesis: true location shift is not equal to 0
m3_2v3 <- wilcox.test(ctDNA.Base.MTM ~ ctDNA.Dynamics,
                      data = circ_data[circ_data$ctDNA.Dynamics %in% c("ctDNA +/+/-", "ctDNA +/+/+"), ],
                      na.rm = TRUE)
Warning: cannot compute exact p-value with ties
print(m3_2v3)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.Base.MTM by ctDNA.Dynamics
W = 2, p-value = 0.001506
alternative hypothesis: true location shift is not equal to 0

#OS by ctDNA at the MRD Window - ACT pts only

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.postNAC == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      5     NA      NA      NA
ctDNA.pCR=2  6      5     11    2.53      NA
ctDNA.pCR=3 10      8      7    2.56      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA post-NAT/TRG", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0    1.000   0.000        1.000        1.000
   24     13       5    0.767   0.092        0.526        0.897

                ctDNA.pCR=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 

                ctDNA.pCR=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0    1.000   0.000      1.00000        1.000
   24      1       8    0.125   0.115      0.00702        0.418
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 39, number of events= 18 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  2.1228    8.3545   0.6529 3.251  0.00115 ** 
ctDNA.pCRTRG4/5 ctDNA (+)  2.3546   10.5336   0.5969 3.945 7.99e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)     8.355    0.11970     2.323     30.04
ctDNA.pCRTRG4/5 ctDNA (+)    10.534    0.09493     3.270     33.94

Concordance= 0.765  (se = 0.044 )
Likelihood ratio test= 19.53  on 2 df,   p=6e-05
Wald test            = 17.01  on 2 df,   p=2e-04
Score (logrank) test = 23.41  on 2 df,   p=8e-06

#RFS by ctDNA at the MRD Window - NAC pts only

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.postNAC == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      2     NA      NA      NA
ctDNA.pCR=2  6      3   8.31    3.58      NA
ctDNA.pCR=3 10      8  18.89   11.66      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="OS - ctDNA post-NAT/TRG", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0        1       0            1            1
   24     15       0        1       0           NA           NA

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      6       0      1.0   0.000        1.000        1.000
   24      1       3      0.5   0.204        0.111        0.804

                ctDNA.pCR=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0    1.000    0.00       1.0000        1.000
   24      2       7    0.225    0.14       0.0342        0.517
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 39, number of events= 13 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  2.7343   15.3983   0.9416 2.904 0.003685 ** 
ctDNA.pCRTRG4/5 ctDNA (+)  2.8771   17.7633   0.8035 3.581 0.000343 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)     15.40    0.06494     2.432     97.49
ctDNA.pCRTRG4/5 ctDNA (+)     17.76    0.05630     3.678     85.80

Concordance= 0.811  (se = 0.04 )
Likelihood ratio test= 19.74  on 2 df,   p=5e-05
Wald test            = 13.12  on 2 df,   p=0.001
Score (logrank) test = 22.59  on 2 df,   p=1e-05

#OS by ctDNA at the MRD Window - NAC pts only

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included == TRUE, ]

circ_data$ctDNA.MRD.Date <- as.Date(circ_data$ctDNA.MRD.Date, format="%m/%d/%Y")
circ_data$Surgery.Date <- as.Date(circ_data$Surgery.Date, format="%m/%d/%Y")
circ_data$Time_to_ctDNA_MRD <- as.numeric(difftime(circ_data$ctDNA.MRD.Date, circ_data$Surgery.Date, units="days"))
median_ctDNA_MRD <- median(circ_data$Time_to_ctDNA_MRD, na.rm=TRUE)
range_ctDNA_MRD <- range(circ_data$Time_to_ctDNA_MRD, na.rm=TRUE)
Q1_ctDNA_MRD <- quantile(circ_data$Time_to_ctDNA_MRD, 0.25, na.rm=TRUE)
Q3_ctDNA_MRD <- quantile(circ_data$Time_to_ctDNA_MRD, 0.75, na.rm=TRUE)
IQR_ctDNA_MRD <- IQR(circ_data$Time_to_ctDNA_MRD, na.rm=TRUE)
cat("Median time from surgery to ctDNA MRD time point:", median_ctDNA_MRD, "days\n")
Median time from surgery to ctDNA MRD time point: 40.5 days
cat("Range:", range_ctDNA_MRD[1], "-", range_ctDNA_MRD[2], "days\n")
Range: 15 - 82 days
cat("Q1 (25th percentile):", Q1_ctDNA_MRD, "days\n")
Q1 (25th percentile): 30.25 days
cat("Q3 (75th percentile):", Q3_ctDNA_MRD, "days\n")
Q3 (75th percentile): 47 days
cat("Interquartile Range (IQR):", IQR_ctDNA_MRD, "days\n")
Interquartile Range (IQR): 16.75 days

#RFS by ctDNA at the MRD Window & ypT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 40     14     NA   23.32      NA
ctDNA.MRD=POSITIVE  7      7   3.57    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA MRD window | All pts", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     40       0    1.000  0.0000        1.000        1.000
   24     18      13    0.628  0.0836        0.442        0.766

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            7            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 47, number of events= 21 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.5604   12.9415   0.5704 4.489 7.17e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     12.94    0.07727     4.231     39.59

Concordance= 0.666  (se = 0.047 )
Likelihood ratio test= 17.26  on 1 df,   p=3e-05
Wald test            = 20.15  on 1 df,   p=7e-06
Score (logrank) test = 31.36  on 1 df,   p=2e-08
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 12.94 (4.23-39.59); p = 0"

#OS by ctDNA at the MRD Window & ypT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 40      6     NA      NA      NA
ctDNA.MRD=POSITIVE 10      8   8.59    5.31      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA MRD window | All pts", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     40       0    1.000  0.0000        1.000        1.000
   24     23       5    0.849  0.0632        0.671        0.935

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0           10            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 50, number of events= 14 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.6769   14.5406   0.5942 4.505 6.64e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     14.54    0.06877     4.537      46.6

Concordance= 0.771  (se = 0.055 )
Likelihood ratio test= 19.56  on 1 df,   p=1e-05
Wald test            = 20.29  on 1 df,   p=7e-06
Score (logrank) test = 33.05  on 1 df,   p=9e-09
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 14.54 (4.54-46.6); p = 0"

#RFS by ctDNA at the MRD Window & ypN

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ACT==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 39     14     NA   23.32      NA
ctDNA.MRD=POSITIVE  6      6   3.54    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA MRD window | ACT treated", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     39       0    1.000   0.000        1.000        1.000
   24     18      13    0.623   0.084        0.437        0.763

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 45, number of events= 20 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.4748   11.8797   0.5874 4.213 2.52e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     11.88    0.08418     3.757     37.57

Concordance= 0.651  (se = 0.048 )
Likelihood ratio test= 14.56  on 1 df,   p=1e-04
Wald test            = 17.75  on 1 df,   p=3e-05
Score (logrank) test = 27.27  on 1 df,   p=2e-07
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 11.88 (3.76-37.57); p = 0"

#OS by ctDNA at the MRD Window & ypN

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ACT==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 39      6     NA      NA      NA
ctDNA.MRD=POSITIVE  7      5   10.3    5.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA MRD window | ACT treated", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     39       0    1.000  0.0000        1.000        1.000
   24     23       5    0.847  0.0636        0.669        0.934

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            7            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 46, number of events= 11 

                     coef exp(coef) se(coef)    z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.3872   10.8835   0.6522 3.66 0.000252 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     10.88    0.09188     3.031     39.08

Concordance= 0.717  (se = 0.071 )
Likelihood ratio test= 11.36  on 1 df,   p=8e-04
Wald test            = 13.4  on 1 df,   p=3e-04
Score (logrank) test = 20.32  on 1 df,   p=7e-06
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 10.88 (3.03-39.08); p = 0"

#RFS by ctDNA at the MRD Window & TRG combination V2 (TRG1/2 vs TRG3-5)

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$NAC==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 35     12     NA   23.32      NA
ctDNA.MRD=POSITIVE  5      5   4.36    3.57      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA MRD window | NAC treated", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     35       0     1.00  0.0000        1.000        1.000
   24     15      11     0.64  0.0892        0.439        0.785

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 40, number of events= 17 

                    coef exp(coef) se(coef)    z Pr(>|z|)    
ctDNA.MRDPOSITIVE 2.2339    9.3362   0.6137 3.64 0.000272 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     9.336     0.1071     2.804     31.08

Concordance= 0.639  (se = 0.051 )
Likelihood ratio test= 10.63  on 1 df,   p=0.001
Wald test            = 13.25  on 1 df,   p=3e-04
Score (logrank) test = 18.98  on 1 df,   p=1e-05
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 9.34 (2.8-31.08); p = 0"

#OS by ctDNA at the MRD Window & TRG combination V2 (TRG1/2 vs TRG3-5)

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$NAC==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 35      6     NA      NA      NA
ctDNA.MRD=POSITIVE  8      6    7.1    5.31      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA MRD window | NAC treated", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     35       0    1.000  0.0000        1.000        1.000
   24     18       5    0.821  0.0741        0.616        0.922

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 43, number of events= 12 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.3851   10.8601   0.6224 3.832 0.000127 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     10.86    0.09208     3.206     36.78

Concordance= 0.742  (se = 0.065 )
Likelihood ratio test= 13.1  on 1 df,   p=3e-04
Wald test            = 14.68  on 1 df,   p=1e-04
Score (logrank) test = 22.15  on 1 df,   p=3e-06
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 10.86 (3.21-36.78); p = 0"

#RFS by ctDNA at the MRD Window & ypTN Characteristics

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      8     NA      NA      NA
ctDNA.Stage.II.TNM=2  4      4   5.10    3.21      NA
ctDNA.Stage.II.TNM=3  9      6  19.34   11.55      NA
ctDNA.Stage.II.TNM=4  3      3   3.51    1.70      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="RFS - ctDNA MRD & ypTN", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000   0.000        1.000        1.000
   24     15       8    0.698   0.091        0.481        0.838

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            4            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0      1.0   0.000       1.0000        1.000
   24      3       5      0.4   0.174       0.0981        0.697

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 47, number of events= 21 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  2.6818   14.6110   0.6876 3.900 9.62e-05 ***
ctDNA.Stage.II.TNMctDNA(-) & T4     1.0893    2.9722   0.5407 2.015   0.0439 *  
ctDNA.Stage.II.TNMctDNA(+) & T4     3.4934   32.8977   0.8353 4.182 2.89e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3    14.611    0.06844     3.796    56.233
ctDNA.Stage.II.TNMctDNA(-) & T4        2.972    0.33645     1.030     8.576
ctDNA.Stage.II.TNMctDNA(+) & T4       32.898    0.03040     6.399   169.126

Concordance= 0.731  (se = 0.051 )
Likelihood ratio test= 21.92  on 3 df,   p=7e-05
Wald test            = 22.7  on 3 df,   p=5e-05
Score (logrank) test = 37.96  on 3 df,   p=3e-08
#Repeat analysis to compare ctDNA MRD (-) vs (+) in T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      8     NA      NA      NA
ctDNA.Stage.II.TNM=2  4      4   5.10    3.21      NA
ctDNA.Stage.II.TNM=3  9      6  19.34   11.55      NA
ctDNA.Stage.II.TNM=4  3      3   3.51    1.70      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="RFS - ctDNA MRD & ypTN", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000   0.000        1.000        1.000
   24     15       8    0.698   0.091        0.481        0.838

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            4            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0      1.0   0.000       1.0000        1.000
   24      3       5      0.4   0.174       0.0981        0.697

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 47, number of events= 21 

                        coef exp(coef) se(coef)      z Pr(>|z|)    
ctDNA.Stage.II.TNM4  0.81163   2.25158  0.80842  1.004   0.3154    
ctDNA.Stage.II.TNM1 -2.68177   0.06844  0.68763 -3.900 9.62e-05 ***
ctDNA.Stage.II.TNM3 -1.59246   0.20342  0.71596 -2.224   0.0261 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   2.25158     0.4441   0.46170   10.9804
ctDNA.Stage.II.TNM1   0.06844    14.6110   0.01778    0.2634
ctDNA.Stage.II.TNM3   0.20342     4.9158   0.05000    0.8276

Concordance= 0.731  (se = 0.051 )
Likelihood ratio test= 21.92  on 3 df,   p=7e-05
Wald test            = 22.7  on 3 df,   p=5e-05
Score (logrank) test = 37.96  on 3 df,   p=3e-08

#OS by ctDNA at the MRD Window & ypTN Characteristics

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      3     NA      NA      NA
ctDNA.Stage.II.TNM=2  5      3  21.48    8.66      NA
ctDNA.Stage.II.TNM=3  9      3  49.70   49.70      NA
ctDNA.Stage.II.TNM=4  5      5   5.31    0.58      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA MRD & ypTN", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000  0.0000        1.000        1.000
   24     18       3    0.875  0.0681        0.658        0.959

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000        1.000        1.000
   24      5       2    0.762   0.148        0.332        0.935

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 50, number of events= 14 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  2.5315   12.5725   0.8498 2.979  0.00289 ** 
ctDNA.Stage.II.TNMctDNA(-) & T4     1.2740    3.5751   0.8169 1.560  0.11886    
ctDNA.Stage.II.TNMctDNA(+) & T4     4.5082   90.7580   0.9252 4.873  1.1e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3    12.573    0.07954     2.377     66.49
ctDNA.Stage.II.TNMctDNA(-) & T4        3.575    0.27971     0.721     17.73
ctDNA.Stage.II.TNMctDNA(+) & T4       90.758    0.01102    14.804    556.40

Concordance= 0.829  (se = 0.056 )
Likelihood ratio test= 27.86  on 3 df,   p=4e-06
Wald test            = 24.63  on 3 df,   p=2e-05
Score (logrank) test = 59.15  on 3 df,   p=9e-13
#Repeat analysis to compare ctDNA post-NAT (-) vs (+) in T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      3     NA      NA      NA
ctDNA.Stage.II.TNM=2  5      3  21.48    8.66      NA
ctDNA.Stage.II.TNM=3  9      3  49.70   49.70      NA
ctDNA.Stage.II.TNM=4  5      5   5.31    0.58      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA MRD & ypTN", ylab= "Overall Survival Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000  0.0000        1.000        1.000
   24     18       3    0.875  0.0681        0.658        0.959

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000        1.000        1.000
   24      5       2    0.762   0.148        0.332        0.935

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 50, number of events= 14 

                        coef exp(coef) se(coef)      z Pr(>|z|)   
ctDNA.Stage.II.TNM4  1.97669   7.21877  0.84482  2.340  0.01930 * 
ctDNA.Stage.II.TNM1 -2.53151   0.07954  0.84981 -2.979  0.00289 **
ctDNA.Stage.II.TNM3 -1.25752   0.28436  0.84413 -1.490  0.13629   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   7.21877     0.1385   1.37833   37.8071
ctDNA.Stage.II.TNM1   0.07954    12.5725   0.01504    0.4207
ctDNA.Stage.II.TNM3   0.28436     3.5167   0.05437    1.4873

Concordance= 0.829  (se = 0.056 )
Likelihood ratio test= 27.86  on 3 df,   p=4e-06
Wald test            = 24.63  on 3 df,   p=2e-05
Score (logrank) test = 59.15  on 3 df,   p=9e-13

#Multivariate cox regression for RFS - ctDNA MRD Window

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 24      5     NA      NA      NA
ctDNA.Stage.II.TNM=2  1      1   1.70      NA      NA
ctDNA.Stage.II.TNM=3 16      9  15.20   10.34      NA
ctDNA.Stage.II.TNM=4  6      6   3.97    3.51      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="RFS - ctDNA MRD & ypN", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     24       0    1.000  0.0000        1.000         1.00
   24     17       4    0.823  0.0807        0.593         0.93

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            1            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000   0.000      1.00000        1.000
   24      1       9    0.148   0.132      0.00842        0.466

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 47, number of events= 21 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0   5.9532  384.9884   1.5428 3.859 0.000114 ***
ctDNA.Stage.II.TNMctDNA(-) & ypN+   2.0297    7.6117   0.6062 3.348 0.000814 ***
ctDNA.Stage.II.TNMctDNA(+) & ypN+   3.6876   39.9503   0.7639 4.827 1.38e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0   384.988   0.002597    18.715   7919.53
ctDNA.Stage.II.TNMctDNA(-) & ypN+     7.612   0.131377     2.320     24.97
ctDNA.Stage.II.TNMctDNA(+) & ypN+    39.950   0.025031     8.939    178.56

Concordance= 0.792  (se = 0.048 )
Likelihood ratio test= 31.15  on 3 df,   p=8e-07
Wald test            = 27.95  on 3 df,   p=4e-06
Score (logrank) test = 54.44  on 3 df,   p=9e-12

#Multivariate cox regression for OS - ctDNA MRD Window

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 24      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  2      2   4.46    0.38      NA
ctDNA.Stage.II.TNM=3 16      4     NA   21.25      NA
ctDNA.Stage.II.TNM=4  8      6   9.46    5.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA MRD & ypN", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     24       0    1.000  0.0000        1.000        1.000
   24     20       1    0.957  0.0425        0.729        0.994

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            2            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000    0.00        1.000        1.000
   24      3       4    0.565    0.19        0.165        0.835

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 50, number of events= 14 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0   5.0035  148.9381   1.1735 4.264 2.01e-05 ***
ctDNA.Stage.II.TNMctDNA(-) & ypN+   1.8810    6.5597   0.9016 2.086    0.037 *  
ctDNA.Stage.II.TNMctDNA(+) & ypN+   3.5092   33.4225   0.8993 3.902 9.53e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0    148.94   0.006714    14.932    1485.5
ctDNA.Stage.II.TNMctDNA(-) & ypN+      6.56   0.152445     1.120      38.4
ctDNA.Stage.II.TNMctDNA(+) & ypN+     33.42   0.029920     5.736     194.8

Concordance= 0.86  (se = 0.04 )
Likelihood ratio test= 26.4  on 3 df,   p=8e-06
Wald test            = 23  on 3 df,   p=4e-05
Score (logrank) test = 46.69  on 3 df,   p=4e-10

#Multivariate cox regression for RFS - ctDNA MRD Window V2 (TRG1/2 vs TRG3-5)

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.MRD == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      6     NA   39.09      NA
ctDNA.pCR=2 12      6  15.60   11.55      NA
ctDNA.pCR=3  3      3   4.36    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA MRD/TRG", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0    1.000  0.0000        1.000        1.000
   24     12       5    0.749  0.0993        0.492        0.889

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     12       0    1.000   0.000        1.000        1.000
   24      4       6    0.417   0.157        0.131        0.686

                ctDNA.pCR=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 38, number of events= 15 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  0.9323    2.5404   0.5794 1.609 0.107610    
ctDNA.pCRTRG4/5 ctDNA (+)  3.0190   20.4704   0.8850 3.411 0.000647 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)      2.54    0.39364     0.816     7.909
ctDNA.pCRTRG4/5 ctDNA (+)     20.47    0.04885     3.612   116.004

Concordance= 0.7  (se = 0.064 )
Likelihood ratio test= 10.66  on 2 df,   p=0.005
Wald test            = 11.83  on 2 df,   p=0.003
Score (logrank) test = 19.3  on 2 df,   p=6e-05

#RFS by ctDNA at the Surveillance Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.MRD == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      3     NA   49.70      NA
ctDNA.pCR=2 12      3     NA   16.09      NA
ctDNA.pCR=3  6      6   5.42    0.58      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="OS - ctDNA MRD/TRG", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0    1.000  0.0000        1.000        1.000
   24     13       2    0.886  0.0776        0.607        0.971

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     12       0      1.0   0.000        1.000        1.000
   24      6       3      0.7   0.145        0.329        0.892

                ctDNA.pCR=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 41, number of events= 12 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  0.6450    1.9061   0.8202 0.786    0.432    
ctDNA.pCRTRG4/5 ctDNA (+)  3.1621   23.6201   0.7401 4.273 1.93e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)     1.906    0.52464    0.3819     9.513
ctDNA.pCRTRG4/5 ctDNA (+)    23.620    0.04234    5.5374   100.753

Concordance= 0.812  (se = 0.065 )
Likelihood ratio test= 18.73  on 2 df,   p=9e-05
Wald test            = 21.36  on 2 df,   p=2e-05
Score (logrank) test = 38.75  on 2 df,   p=4e-09

#OS by ctDNA at the Surveillance Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_data$TRGv2 <- factor(circ_data$TRGv2, levels = c("TRG1/2", "TRG3/4/5"))

circ_data$ctDNA.pCR <- NA
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & TRGv2 == "TRG1/2" ~ "1",
    ctDNA.MRD == "NEGATIVE" & TRGv2 == "TRG3/4/5" ~ "2",
    ctDNA.MRD == "POSITIVE" & TRGv2 == "TRG3/4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1  7      0     NA      NA      NA
ctDNA.pCR=2 28     12  39.09   15.20      NA
ctDNA.pCR=3  4      4   3.97    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA MRD/TRG", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("TRG1/2 ctDNA (-)","TRG3/4/5 ctDNA (-)", "TRG3/4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      7       0        1       0            1            1
   24      6       0        1       0           NA           NA

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     28       0     1.00   0.000        1.000        1.000
   24     10      11     0.54   0.106        0.317        0.718

                ctDNA.pCR=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            4            0            1            0            1            1 
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2 ctDNA (-)","TRG3/4/5 ctDNA (-)", "TRG3/4/5 ctDNA (+)"))
cox_fit <- coxphf(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
coxphf(formula = surv_object ~ ctDNA.pCR, data = circ_data)

Model fitted by Penalized ML
Confidence intervals and p-values by Profile Likelihood 

                                coef se(coef)  exp(coef) lower 0.95 upper 0.95     Chisq            p
ctDNA.pCRTRG3/4/5 ctDNA (-) 2.273832 1.501459   9.716563   1.271915   1246.883  5.185271 2.277912e-02
ctDNA.pCRTRG3/4/5 ctDNA (+) 4.714845 1.654749 111.591483   9.420380  15951.959 16.867182 4.008876e-05

Likelihood ratio test=16.87033 on 2 df, p=0.0002170973, n=39
Wald test = 12.62666 on 2 df, p = 0.001811992

Covariance-Matrix:
                            ctDNA.pCRTRG3/4/5 ctDNA (-) ctDNA.pCRTRG3/4/5 ctDNA (+)
ctDNA.pCRTRG3/4/5 ctDNA (-)                    2.254380                    2.192069
ctDNA.pCRTRG3/4/5 ctDNA (+)                    2.192069                    2.738195
LS0tCnRpdGxlOiAiQUdFTyBQTEFHQVNUX0NsaW5pY2FsIEZpbmFsIGFuYWx5c2lzXyByZXZpc2lvbnMgMDMyNDIwMjUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KbGlicmFyeShzd2ltcGxvdCkKbGlicmFyeShjb3hwaGYpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShndGFibGUpCmxpYnJhcnkocmVhZHIpIApsaWJyYXJ5KG1vc2FpYykKbGlicmFyeShkcGx5cikgCmxpYnJhcnkoc3Vydml2YWwpIApsaWJyYXJ5KHN1cnZtaW5lcikgCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoY294cGhmKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShndHN1bW1hcnkpCmxpYnJhcnkoZmxleHRhYmxlKQpsaWJyYXJ5KHBhcmFtZXRlcnMpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoc3Vydml2YWwpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShvcGVueGxzeCkKbGlicmFyeSh3cml0ZXhsKQpsaWJyYXJ5KHJtcykKbGlicmFyeShwUk9DKQpsaWJyYXJ5KERUKQoKI2N0RE5BIERldGVjdGlvbiByYXRlIGJ5IFN0YWdlIGFuZCBXaW5kb3cKYGBge3J9CiNCYXNlbGluZQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJGN0RE5BLkJhc2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5CYXNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEuQmFzZSAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5CYXNlLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCgojQzJEMQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJGN0RE5BLkMyRDEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEuQzJEMSAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5DMkQxLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCgojcG9zdC1OQUMgV2luZG93CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEkY3RETkEucG9zdE5BQyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNpcmNfZGF0YSRTdGFnZSA8LSBmYWN0b3IoY2lyY19kYXRhJFN0YWdlLCBsZXZlbHM9YygiSSIsIklJIiwiSUlJIikpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCBjdEROQS5wb3N0TkFDICVpbiUgYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSkKcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1zdW0pCnRvdGFsX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPWxlbmd0aCkKY29tYmluZWRfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gdG90YWxfY291bnRzX2J5X3N0YWdlJEdyb3VwLjEsCiAgVG90YWxfQ291bnQgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCwKICBQb3NpdGl2ZV9Db3VudCA9IHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4LAogIFJhdGUgPSAocG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHggLyB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCikKY29tYmluZWRfZGF0YSRSYXRlIDwtIHNwcmludGYoIiUuMmYlJSIsIGNvbWJpbmVkX2RhdGEkUmF0ZSkKb3ZlcmFsbF90b3RhbF9jb3VudCA8LSBucm93KGNpcmNfZGF0YSkKb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCA8LSBucm93KGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiLF0pCm92ZXJhbGxfcG9zaXRpdml0eV9yYXRlIDwtIChvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IC8gb3ZlcmFsbF90b3RhbF9jb3VudCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCm92ZXJhbGxfcm93IDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSAiT3ZlcmFsbCIsCiAgVG90YWxfQ291bnQgPSBvdmVyYWxsX3RvdGFsX2NvdW50LAogIFBvc2l0aXZlX0NvdW50ID0gb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCwKICBSYXRlID0gc3ByaW50ZigiJS4yZiUlIiwgb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUpCikKY29tYmluZWRfZGF0YSA8LSByYmluZChjb21iaW5lZF9kYXRhLCBvdmVyYWxsX3JvdykKcHJpbnQoY29tYmluZWRfZGF0YSkKCiNNUkQgV2luZG93CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEuTVJEICVpbiUgYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSkKcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuTVJEID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuTVJELCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiLF0pCm92ZXJhbGxfcG9zaXRpdml0eV9yYXRlIDwtIChvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IC8gb3ZlcmFsbF90b3RhbF9jb3VudCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCm92ZXJhbGxfcm93IDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSAiT3ZlcmFsbCIsCiAgVG90YWxfQ291bnQgPSBvdmVyYWxsX3RvdGFsX2NvdW50LAogIFBvc2l0aXZlX0NvdW50ID0gb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCwKICBSYXRlID0gc3ByaW50ZigiJS4yZiUlIiwgb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUpCikKY29tYmluZWRfZGF0YSA8LSByYmluZChjb21iaW5lZF9kYXRhLCBvdmVyYWxsX3JvdykKcHJpbnQoY29tYmluZWRfZGF0YSkKCiNPbi10cmVhdG1lbnQKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRjdEROQS5vbkFDVCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLm9uQUNULCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEub25BQ1QgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5vbkFDVCA9PSAiUE9TSVRJVkUiLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1zdW0pCnRvdGFsX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLm9uQUNULCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLm9uQUNUID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQoKI1N1cnZlaWxsYW5jZSBXaW5kb3cKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNpcmNfZGF0YSRTdGFnZSA8LSBmYWN0b3IoY2lyY19kYXRhJFN0YWdlLCBsZXZlbHM9YygiSSIsIklJIiwiSUlJIikpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCBjdEROQS5zdXJ2ZWlsbGFuY2UgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPWxlbmd0aCkKY29tYmluZWRfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gdG90YWxfY291bnRzX2J5X3N0YWdlJEdyb3VwLjEsCiAgVG90YWxfQ291bnQgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCwKICBQb3NpdGl2ZV9Db3VudCA9IHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4LAogIFJhdGUgPSAocG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHggLyB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCikKY29tYmluZWRfZGF0YSRSYXRlIDwtIHNwcmludGYoIiUuMmYlJSIsIGNvbWJpbmVkX2RhdGEkUmF0ZSkKb3ZlcmFsbF90b3RhbF9jb3VudCA8LSBucm93KGNpcmNfZGF0YSkKb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCA8LSBucm93KGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQoKI1Bvc3QtQUNUIFdpbmRvdwpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJGN0RE5BLnBvc3RBQ1QgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wb3N0QUNULCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEucG9zdEFDVCAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLnBvc3RBQ1QgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5wb3N0QUNULCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3RBQ1QgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCgojUG9zdC1yZWxhcHNlIFdpbmRvdwpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJGN0RE5BLnBvc3RSZWxhcHNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucG9zdFJlbGFwc2UsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNpcmNfZGF0YSRTdGFnZSA8LSBmYWN0b3IoY2lyY19kYXRhJFN0YWdlLCBsZXZlbHM9YygiSSIsIklJIiwiSUlJIikpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCBjdEROQS5wb3N0UmVsYXBzZSAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLnBvc3RSZWxhcHNlID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEucG9zdFJlbGFwc2UsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPWxlbmd0aCkKY29tYmluZWRfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gdG90YWxfY291bnRzX2J5X3N0YWdlJEdyb3VwLjEsCiAgVG90YWxfQ291bnQgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCwKICBQb3NpdGl2ZV9Db3VudCA9IHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4LAogIFJhdGUgPSAocG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHggLyB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCikKY29tYmluZWRfZGF0YSRSYXRlIDwtIHNwcmludGYoIiUuMmYlJSIsIGNvbWJpbmVkX2RhdGEkUmF0ZSkKb3ZlcmFsbF90b3RhbF9jb3VudCA8LSBucm93KGNpcmNfZGF0YSkKb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCA8LSBucm93KGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdFJlbGFwc2UgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCmBgYAoKCgoKI05lb2FkanV2YW50IFRyZWF0bWVudCBkdXJhdGlvbgpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZCA9PSBUUlVFLCBdCgpjaXJjX2RhdGEkTkFDLlN0YXJ0IDwtIGFzLkRhdGUoY2lyY19kYXRhJE5BQy5TdGFydCwgZm9ybWF0PSIlbS8lZC8lWSIpCmNpcmNfZGF0YSROQUMuRW5kIDwtIGFzLkRhdGUoY2lyY19kYXRhJE5BQy5FbmQsIGZvcm1hdD0iJW0vJWQvJVkiKQpjaXJjX2RhdGEkTkFDLkR1cmF0aW9uIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUoY2lyY19kYXRhJE5BQy5FbmQsIGNpcmNfZGF0YSROQUMuU3RhcnQsIHVuaXRzPSJkYXlzIikpCm1lZGlhbl9kdXJhdGlvbiA8LSBtZWRpYW4oY2lyY19kYXRhJE5BQy5EdXJhdGlvbiwgbmEucm09VFJVRSkKcmFuZ2VfZHVyYXRpb24gPC0gcmFuZ2UoY2lyY19kYXRhJE5BQy5EdXJhdGlvbiwgbmEucm09VFJVRSkKUTEgPC0gcXVhbnRpbGUoY2lyY19kYXRhJE5BQy5EdXJhdGlvbiwgMC4yNSwgbmEucm09VFJVRSkKUTMgPC0gcXVhbnRpbGUoY2lyY19kYXRhJE5BQy5EdXJhdGlvbiwgMC43NSwgbmEucm09VFJVRSkKSVFSX3ZhbHVlIDwtIElRUihjaXJjX2RhdGEkTkFDLkR1cmF0aW9uLCBuYS5ybT1UUlVFKQpjYXQoIk1lZGlhbiBOQUMgRHVyYXRpb246IiwgbWVkaWFuX2R1cmF0aW9uLCAiZGF5c1xuIikKY2F0KCJSYW5nZSBvZiBOQUMgRHVyYXRpb246IiwgcmFuZ2VfZHVyYXRpb25bMV0sICItIiwgcmFuZ2VfZHVyYXRpb25bMl0sICJkYXlzXG4iKQpjYXQoIlExICgyNXRoIHBlcmNlbnRpbGUpOiIsIFExLCAiZGF5c1xuIikKY2F0KCJRMyAoNzV0aCBwZXJjZW50aWxlKToiLCBRMywgImRheXNcbiIpCmNhdCgiSW50ZXJxdWFydGlsZSBSYW5nZSAoSVFSKToiLCBJUVJfdmFsdWUsICJkYXlzXG4iKQpgYGAKCiNUaW1lIG9mIGN0RE5BIGRyYXdzIGZyb20gc3RhcnQgYW5kIGVuZCBvZiBuZW9kanV2YW50IHRyZWF0bWVudApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZCA9PSBUUlVFLCBdCgpjaXJjX2RhdGEkTkFDLlN0YXJ0IDwtIGFzLkRhdGUoY2lyY19kYXRhJE5BQy5TdGFydCwgZm9ybWF0PSIlbS8lZC8lWSIpCmNpcmNfZGF0YSROQUMuRW5kIDwtIGFzLkRhdGUoY2lyY19kYXRhJE5BQy5FbmQsIGZvcm1hdD0iJW0vJWQvJVkiKQpjaXJjX2RhdGEkY3RETkEuQzJEMS5EYXRlIDwtIGFzLkRhdGUoY2lyY19kYXRhJGN0RE5BLkMyRDEuRGF0ZSwgZm9ybWF0PSIlbS8lZC8lWSIpCmNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLkRhdGUgPC0gYXMuRGF0ZShjaXJjX2RhdGEkY3RETkEucG9zdE5BQy5EYXRlLCBmb3JtYXQ9IiVtLyVkLyVZIikKCmNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX0MyRDEgPC0gYXMubnVtZXJpYyhkaWZmdGltZShjaXJjX2RhdGEkY3RETkEuQzJEMS5EYXRlLCBjaXJjX2RhdGEkTkFDLlN0YXJ0LCB1bml0cz0iZGF5cyIpKQpjaXJjX2RhdGEkVGltZV90b19jdEROQV9wb3N0TkFDIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUoY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMuRGF0ZSwgY2lyY19kYXRhJE5BQy5FbmQsIHVuaXRzPSJkYXlzIikpCgptZWRpYW5fY3RETkFfQzJEMSA8LSBtZWRpYW4oY2lyY19kYXRhJFRpbWVfdG9fY3RETkFfQzJEMSwgbmEucm09VFJVRSkKcmFuZ2VfY3RETkFfQzJEMSA8LSByYW5nZShjaXJjX2RhdGEkVGltZV90b19jdEROQV9DMkQxLCBuYS5ybT1UUlVFKQpRMV9jdEROQV9DMkQxIDwtIHF1YW50aWxlKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX0MyRDEsIDAuMjUsIG5hLnJtPVRSVUUpClEzX2N0RE5BX0MyRDEgPC0gcXVhbnRpbGUoY2lyY19kYXRhJFRpbWVfdG9fY3RETkFfQzJEMSwgMC43NSwgbmEucm09VFJVRSkKSVFSX2N0RE5BX0MyRDEgPC0gSVFSKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX0MyRDEsIG5hLnJtPVRSVUUpCm1lZGlhbl9jdEROQV9wb3N0TkFDIDwtIG1lZGlhbihjaXJjX2RhdGEkVGltZV90b19jdEROQV9wb3N0TkFDLCBuYS5ybT1UUlVFKQpyYW5nZV9jdEROQV9wb3N0TkFDIDwtIHJhbmdlKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX3Bvc3ROQUMsIG5hLnJtPVRSVUUpClExX2N0RE5BX3Bvc3ROQUMgPC0gcXVhbnRpbGUoY2lyY19kYXRhJFRpbWVfdG9fY3RETkFfcG9zdE5BQywgMC4yNSwgbmEucm09VFJVRSkKUTNfY3RETkFfcG9zdE5BQyA8LSBxdWFudGlsZShjaXJjX2RhdGEkVGltZV90b19jdEROQV9wb3N0TkFDLCAwLjc1LCBuYS5ybT1UUlVFKQpJUVJfY3RETkFfcG9zdE5BQyA8LSBJUVIoY2lyY19kYXRhJFRpbWVfdG9fY3RETkFfcG9zdE5BQywgbmEucm09VFJVRSkKY2F0KCJNZWRpYW4gdGltZSBmcm9tIE5BQyBzdGFydCB0byBjdEROQSBkcmF3IGR1cmluZyBOQUM6IiwgbWVkaWFuX2N0RE5BX0MyRDEsICJkYXlzXG4iKQpjYXQoIlJhbmdlOiIsIHJhbmdlX2N0RE5BX0MyRDFbMV0sICItIiwgcmFuZ2VfY3RETkFfQzJEMVsyXSwgImRheXNcbiIpCmNhdCgiUTEgKDI1dGggcGVyY2VudGlsZSk6IiwgUTFfY3RETkFfQzJEMSwgImRheXNcbiIpCmNhdCgiUTMgKDc1dGggcGVyY2VudGlsZSk6IiwgUTNfY3RETkFfQzJEMSwgImRheXNcbiIpCmNhdCgiSW50ZXJxdWFydGlsZSBSYW5nZSAoSVFSKToiLCBJUVJfY3RETkFfQzJEMSwgImRheXNcblxuIikKCmNhdCgiTWVkaWFuIHRpbWUgZnJvbSBOQUMgZW5kIHRvIGN0RE5BIGRyYXcgcG9zdC1OQUM6IiwgbWVkaWFuX2N0RE5BX3Bvc3ROQUMsICJkYXlzXG4iKQpjYXQoIlJhbmdlOiIsIHJhbmdlX2N0RE5BX3Bvc3ROQUNbMV0sICItIiwgcmFuZ2VfY3RETkFfcG9zdE5BQ1syXSwgImRheXNcbiIpCmNhdCgiUTEgKDI1dGggcGVyY2VudGlsZSk6IiwgUTFfY3RETkFfcG9zdE5BQywgImRheXNcbiIpCmNhdCgiUTMgKDc1dGggcGVyY2VudGlsZSk6IiwgUTNfY3RETkFfcG9zdE5BQywgImRheXNcbiIpCmNhdCgiSW50ZXJxdWFydGlsZSBSYW5nZSAoSVFSKToiLCBJUVJfY3RETkFfcG9zdE5BQywgImRheXNcbiIpCmBgYAoKI0RlbW9ncmFwaGljcyBUYWJsZQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGFfc3Vic2V0IDwtIGNpcmNfZGF0YSAlPiUKICBzZWxlY3QoCiAgICBBZ2UsCiAgICBHZW5kZXIsCiAgICBQcmltU2l0ZSwKICAgIE5BQywKICAgIE5BQy5SZWdpbWVuLAogICAgVFJHLk1hbmRhcmQsCiAgICBUTk0sCiAgICBTdGFnZSwKICAgIEdyYWRlLAogICAgTGF1cmVuLkNsYXNzLAogICAgTWFyZ2lucywKICAgIEFDVCwKICAgIEFDVC5SZWdpbWVuLAogICAgREZTLkV2ZW50LAogICAgT1MuRXZlbnQsCiAgICBGVS5tb250aHMpICU+JQogIG11dGF0ZSgKICAgIEFnZSA9IGFzLm51bWVyaWMoQWdlKSwKICAgIEdlbmRlciA9IGZhY3RvcihHZW5kZXIsIGxldmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIikpLAogICAgUHJpbVNpdGUgPSBmYWN0b3IoUHJpbVNpdGUsIGxldmVscyA9IGMoIlN0b21hY2giLCAiRy9KIiwgIk9lc29waGFndXMiKSksCiAgICBOQUMgPSBmYWN0b3IoTkFDLCBsZXZlbHMgPSBjKCJUUlVFIiwgIkZBTFNFIiksIGxhYmVscyA9IGMoIk5lb2FkanV2YW50IFRoZXJhcHkiLCAiVXBmcm9udCBTdXJnZXJ5IikpLAogICAgTkFDLlJlZ2ltZW4gPSBmYWN0b3IoTkFDLlJlZ2ltZW4pLAogICAgVFJHLk1hbmRhcmQgPSBmYWN0b3IoVFJHLk1hbmRhcmQsIGxldmVscyA9IGMoIlRSRzEiLCJUUkcyIiwgIlRSRzMiLCAiVFJHNCIsICJUUkc1IikpLAogICAgVE5NID0gZmFjdG9yKFROTSwgbGV2ZWxzID0gYygiVDAtVGlzTjBNMCIsIlQxLVQyTjAiLCAiVDItVDNOMC1OMSIsICJUMk4xLU4yIiwgIlQzTjItTjMiLCAiVDROMC1OMSIsICJUNE4yLU4zIikpLAogICAgU3RhZ2UgPSBmYWN0b3IoU3RhZ2UsIGxldmVscyA9IGMoIjAiLCJJIiwiSUkiLCAiSUlJIikpLAogICAgR3JhZGUgPSBmYWN0b3IoR3JhZGUsIGxldmVscyA9IGMoIkcxIiwgIkcyIiwgIkczIikpLAogICAgTGF1cmVuLkNsYXNzID0gZmFjdG9yKExhdXJlbi5DbGFzcyksCiAgICBNYXJnaW5zID0gZmFjdG9yKE1hcmdpbnMsIGxldmVscyA9IGMoIlIwIiwgIlIxIikpLAogICAgQUNUID0gZmFjdG9yKEFDVCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJBZGp1dmFudCBUcmVhdG1lbnQiLCAiT2JzZXJ2YXRpb24iKSksCiAgICBBQ1QuUmVnaW1lbiA9IGZhY3RvcihBQ1QuUmVnaW1lbiksCiAgICBERlMuRXZlbnQgPSBmYWN0b3IoREZTLkV2ZW50LCBsZXZlbHMgPSBjKCJUUlVFIiwgIkZBTFNFIiksIGxhYmVscyA9IGMoIlJlY3VycmVuY2UiLCAiTm8gUmVjdXJyZW5jZSIpKSwKICAgIE9TLkV2ZW50ID0gZmFjdG9yKE9TLkV2ZW50LCBsZXZlbHMgPSBjKCJUUlVFIiwgIkZBTFNFIiksIGxhYmVscyA9IGMoIkRlY2Vhc2VkIiwgIkFsaXZlIikpLAogICAgRlUubW9udGhzID0gYXMubnVtZXJpYyhGVS5tb250aHMpKQp0YWJsZTEgPC0gY2lyY19kYXRhX3N1YnNldCAlPiUKICB0Ymxfc3VtbWFyeSgKICAgIHN0YXRpc3RpYyA9IGxpc3QoCiAgICAgIGFsbF9jb250aW51b3VzKCkgfiAie21lZGlhbn0gKHttaW59IC0ge21heH0pIiwKICAgICAgYWxsX2NhdGVnb3JpY2FsKCkgfiAie259ICh7cH0lKSIpKSAlPiUKICBib2xkX2xhYmVscygpCnRhYmxlMQpmaXQxIDwtIGFzX2ZsZXhfdGFibGUoCiAgdGFibGUxLAogIGluY2x1ZGUgPSBldmVyeXRoaW5nKCksCiAgcmV0dXJuX2NhbGxzID0gRkFMU0UKKQpmaXQxCnNhdmVfYXNfZG9jeChmaXQxLCBwYXRoPSAifi9Eb3dubG9hZHMvdGFibGUxLmRvY3giKQpgYGAKCgojRGVtb2dyYXBoaWNzIFRhYmxlIGZvciB0aG9zZSB0aGF0IGluY2x1ZGVkIHZzIGV4Y2x1ZGVkIGZyb20gdGhlIHN0dWR5CmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCgpjaXJjX2RhdGFfc3Vic2V0MSA8LSBjaXJjX2RhdGEgJT4lCiAgc2VsZWN0KAogICAgQWdlLAogICAgR2VuZGVyLAogICAgUHJpbVNpdGUsCiAgICBOQUMsCiAgICBOQUMuUmVnaW1lbiwKICAgIFRSRy5NYW5kYXJkLAogICAgVE5NLAogICAgU3RhZ2UsCiAgICBHcmFkZSwKICAgIExhdXJlbi5DbGFzcywKICAgIE1hcmdpbnMsCiAgICBBQ1QsCiAgICBBQ1QuUmVnaW1lbiwKICAgIERGUy5FdmVudCwKICAgIE9TLkV2ZW50LAogICAgRlUubW9udGhzKSAlPiUKICBtdXRhdGUoCiAgICBBZ2UgPSBhcy5udW1lcmljKEFnZSksCiAgICBHZW5kZXIgPSBmYWN0b3IoR2VuZGVyLCBsZXZlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKSwKICAgIFByaW1TaXRlID0gZmFjdG9yKFByaW1TaXRlLCBsZXZlbHMgPSBjKCJTdG9tYWNoIiwgIkcvSiIsICJPZXNvcGhhZ3VzIikpLAogICAgTkFDID0gZmFjdG9yKE5BQywgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJOZW9hZGp1dmFudCBUaGVyYXB5IiwgIlVwZnJvbnQgU3VyZ2VyeSIpKSwKICAgIE5BQy5SZWdpbWVuID0gZmFjdG9yKE5BQy5SZWdpbWVuKSwKICAgIFRSRy5NYW5kYXJkID0gZmFjdG9yKFRSRy5NYW5kYXJkLCBsZXZlbHMgPSBjKCJUUkcxIiwiVFJHMiIsICJUUkczIiwgIlRSRzQiLCAiVFJHNSIpKSwKICAgIFROTSA9IGZhY3RvcihUTk0sIGxldmVscyA9IGMoIlQwLVRpc04wTTAiLCJUMS1UMk4wIiwgIlQyLVQzTjAtTjEiLCAiVDJOMS1OMiIsICJUM04yLU4zIiwgIlQ0TjAtTjEiLCAiVDROMi1OMyIpKSwKICAgIFN0YWdlID0gZmFjdG9yKFN0YWdlLCBsZXZlbHMgPSBjKCIwIiwiSSIsIklJIiwgIklJSSIpKSwKICAgIEdyYWRlID0gZmFjdG9yKEdyYWRlLCBsZXZlbHMgPSBjKCJHMSIsICJHMiIsICJHMyIpKSwKICAgIExhdXJlbi5DbGFzcyA9IGZhY3RvcihMYXVyZW4uQ2xhc3MpLAogICAgTWFyZ2lucyA9IGZhY3RvcihNYXJnaW5zLCBsZXZlbHMgPSBjKCJSMCIsICJSMSIpKSwKICAgIEFDVCA9IGZhY3RvcihBQ1QsIGxldmVscyA9IGMoIlRSVUUiLCAiRkFMU0UiKSwgbGFiZWxzID0gYygiQWRqdXZhbnQgVHJlYXRtZW50IiwgIk9ic2VydmF0aW9uIikpLAogICAgQUNULlJlZ2ltZW4gPSBmYWN0b3IoQUNULlJlZ2ltZW4pLAogICAgREZTLkV2ZW50ID0gZmFjdG9yKERGUy5FdmVudCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJSZWN1cnJlbmNlIiwgIk5vIFJlY3VycmVuY2UiKSksCiAgICBPUy5FdmVudCA9IGZhY3RvcihPUy5FdmVudCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJEZWNlYXNlZCIsICJBbGl2ZSIpKSwKICAgIEZVLm1vbnRocyA9IGFzLm51bWVyaWMoRlUubW9udGhzKSkKCmNpcmNfZGF0YTEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQoKY2lyY19kYXRhX3N1YnNldDIgPC0gY2lyY19kYXRhICU+JQogIHNlbGVjdCgKICAgIEFnZSwKICAgIEdlbmRlciwKICAgIFByaW1TaXRlLAogICAgTkFDLAogICAgTkFDLlJlZ2ltZW4sCiAgICBUUkcuTWFuZGFyZCwKICAgIFROTSwKICAgIFN0YWdlLAogICAgR3JhZGUsCiAgICBMYXVyZW4uQ2xhc3MsCiAgICBNYXJnaW5zLAogICAgQUNULAogICAgQUNULlJlZ2ltZW4sCiAgICBERlMuRXZlbnQsCiAgICBPUy5FdmVudCwKICAgIEZVLm1vbnRocywKICAgIEluY2x1ZGVkKSAlPiUKICBtdXRhdGUoCiAgICBBZ2UgPSBhcy5udW1lcmljKEFnZSksCiAgICBHZW5kZXIgPSBmYWN0b3IoR2VuZGVyLCBsZXZlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKSwKICAgIFByaW1TaXRlID0gZmFjdG9yKFByaW1TaXRlLCBsZXZlbHMgPSBjKCJTdG9tYWNoIiwgIkcvSiIsICJPZXNvcGhhZ3VzIikpLAogICAgTkFDID0gZmFjdG9yKE5BQywgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJOZW9hZGp1dmFudCBUaGVyYXB5IiwgIlVwZnJvbnQgU3VyZ2VyeSIpKSwKICAgIE5BQy5SZWdpbWVuID0gZmFjdG9yKE5BQy5SZWdpbWVuKSwKICAgIFRSRy5NYW5kYXJkID0gZmFjdG9yKFRSRy5NYW5kYXJkLCBsZXZlbHMgPSBjKCJUUkcxIiwiVFJHMiIsICJUUkczIiwgIlRSRzQiLCAiVFJHNSIpKSwKICAgIFROTSA9IGZhY3RvcihUTk0sIGxldmVscyA9IGMoIlQwLVRpc04wTTAiLCJUMS1UMk4wIiwgIlQyLVQzTjAtTjEiLCAiVDJOMS1OMiIsICJUM04yLU4zIiwgIlQ0TjAtTjEiLCAiVDROMi1OMyIpKSwKICAgIFN0YWdlID0gZmFjdG9yKFN0YWdlLCBsZXZlbHMgPSBjKCIwIiwiSSIsIklJIiwgIklJSSIpKSwKICAgIEdyYWRlID0gZmFjdG9yKEdyYWRlLCBsZXZlbHMgPSBjKCJHMSIsICJHMiIsICJHMyIpKSwKICAgIExhdXJlbi5DbGFzcyA9IGZhY3RvcihMYXVyZW4uQ2xhc3MpLAogICAgTWFyZ2lucyA9IGZhY3RvcihNYXJnaW5zLCBsZXZlbHMgPSBjKCJSMCIsICJSMSIpKSwKICAgIEFDVCA9IGZhY3RvcihBQ1QsIGxldmVscyA9IGMoIlRSVUUiLCAiRkFMU0UiKSwgbGFiZWxzID0gYygiQWRqdXZhbnQgVHJlYXRtZW50IiwgIk9ic2VydmF0aW9uIikpLAogICAgQUNULlJlZ2ltZW4gPSBmYWN0b3IoQUNULlJlZ2ltZW4pLAogICAgREZTLkV2ZW50ID0gZmFjdG9yKERGUy5FdmVudCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJSZWN1cnJlbmNlIiwgIk5vIFJlY3VycmVuY2UiKSksCiAgICBPUy5FdmVudCA9IGZhY3RvcihPUy5FdmVudCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJEZWNlYXNlZCIsICJBbGl2ZSIpKSwKICAgIEZVLm1vbnRocyA9IGFzLm51bWVyaWMoRlUubW9udGhzKSwKICAgIEluY2x1ZGVkID0gZmFjdG9yKEluY2x1ZGVkLCBsZXZlbHMgPSBjKCJUUlVFIiwgIkZBTFNFIiksIGxhYmVscyA9IGMoIkluY2x1ZGVkIiwgIkV4Y2x1ZGVkIikpKQpPdmVyYWxsIDwtIGNpcmNfZGF0YV9zdWJzZXQxICU+JQogIHRibF9zdW1tYXJ5KAogICAgc3RhdGlzdGljID0gbGlzdCgKICAgICAgYWxsX2NvbnRpbnVvdXMoKSB+ICJ7bWVkaWFufSAoe21pbn0gLSB7bWF4fSkiLAogICAgICBhbGxfY2F0ZWdvcmljYWwoKSB+ICJ7bn0gKHtwfSUpIikpICU+JQogIGJvbGRfbGFiZWxzKCkKT3ZlcmFsbAoKQnljdEROQV9NUkQgPC0gY2lyY19kYXRhX3N1YnNldDIgJT4lCiAgdGJsX3N1bW1hcnkoCiAgICBieSA9IEluY2x1ZGVkLCAjIFN1Ymdyb3VwIGJ5IEluY2x1ZGVkCiAgICBzdGF0aXN0aWMgPSBsaXN0KAogICAgICBhbGxfY29udGludW91cygpIH4gInttZWRpYW59ICh7bWlufSAtIHttYXh9KSIsCiAgICAgIGFsbF9jYXRlZ29yaWNhbCgpIH4gIntufSAoe3B9JSkiKSkgJT4lCiAgYWRkX3AodGVzdCA9IGFsbF9jYXRlZ29yaWNhbCgpIH4gImZpc2hlci50ZXN0IiwgcHZhbHVlX2Z1biA9IH5zdHlsZV9wdmFsdWUocC5hZGp1c3QoLngsIG1ldGhvZCA9ICJib25mZXJyb25pIikpKSAlPiUKICBib2xkX2xhYmVscygpCkJ5Y3RETkFfTVJECgptZXJnZWRfdGFibGUgPC0gdGJsX21lcmdlKHRibHM9bGlzdChPdmVyYWxsLCBCeWN0RE5BX01SRCkpCm1lcmdlZF90YWJsZQoKZml0MSA8LSBhc19mbGV4X3RhYmxlKAogIG1lcmdlZF90YWJsZSwKICBpbmNsdWRlID0gZXZlcnl0aGluZygpLAogIHJldHVybl9jYWxscyA9IEZBTFNFKQpmaXQxCnNhdmVfYXNfZG9jeChmaXQxLCBwYXRoPSAifi9Eb3dubG9hZHMvbWVyZ2VkX3RhYmxlLmRvY3giKQpgYGAKCiNSRlMgYnkgaW5jbHVzaW9uIHN0YXR1cwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5JbmNsdWRlZCwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gSW5jbHVkZWQsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IlJGUyAtIEluY2x1c2lvbiBzdGF0dXMiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIkluY2x1ZGVkIiwgIkV4Y2x1ZGVkIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkSW5jbHVkZWQgPC0gZmFjdG9yKGNpcmNfZGF0YSRJbmNsdWRlZCwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gSW5jbHVkZWQsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI09TIGJ5IGluY2x1c2lvbiBzdGF0dXMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfkluY2x1ZGVkLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gSW5jbHVkZWQsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9Ik9TIC0gSW5jbHVzaW9uIHN0YXR1cyIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIkluY2x1ZGVkIiwgIkV4Y2x1ZGVkIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkSW5jbHVkZWQgPC0gZmFjdG9yKGNpcmNfZGF0YSRJbmNsdWRlZCwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gSW5jbHVkZWQsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI0hlYXRtYXAgd2l0aCBDbGluaWNhbCAmIEdlbm9taWNzIEZhY3RvcnMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JSBhcnJhbmdlKFN0YWdlKQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmhhIDwtIEhlYXRtYXBBbm5vdGF0aW9uKAogIFN0YWdlID0gY2lyY19kYXRhJFN0YWdlLAogIEdlbmRlciA9IGNpcmNfZGF0YSRHZW5kZXIsCiAgUHJpbVNpdGUgPSBjaXJjX2RhdGEkUHJpbVNpdGUsCiAgTkFDID0gY2lyY19kYXRhJE5BQywKICBBQ1QgPSBjaXJjX2RhdGEkQUNULAogIGN0RE5BLkJhc2UgPSBjaXJjX2RhdGEkY3RETkEuQmFzZSwKICBjdEROQS5DMkQxID0gY2lyY19kYXRhJGN0RE5BLkMyRDEsCiAgY3RETkEucG9zdE5BQyA9IGNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLAogIGN0RE5BLk1SRCA9IGNpcmNfZGF0YSRjdEROQS5NUkQsCiAgY3RETkEuc3VydmVpbGxhbmNlID0gY2lyY19kYXRhJGN0RE5BLnN1cnZlaWxsYW5jZSwKICBERlMuRXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50LAogIE9TLkV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50LAogIAogIGNvbCA9IGxpc3QoU3RhZ2UgPSBjKCIwIiA9ICJzZWFncmVlbjEiLCAiSSIgPSAic2VhZ3JlZW4xIiwgIklJIiA9ICJvcmFuZ2UiLCAiSUlJIiA9ICJwdXJwbGUiKSwKICAgIEdlbmRlciA9IGMoIkZlbWFsZSIgPSAiZ29sZGVucm9kIiAsICJNYWxlIiA9ICJibHVlNCIpLAogICAgUHJpbVNpdGUgPSBjKCJTdG9tYWNoIiA9ICJicm93biIsICJHL0oiID0gImRhcmtncmVlbiIsICJPZXNvcGhhZ3VzIiA9ICJvcmFuZ2U0IiksCiAgICBOQUMgPSBjKCJGQUxTRSIgPSAiY29ybmZsb3dlcmJsdWUiLCAiVFJVRSIgPSJkYXJrbWFnZW50YSIpLAogICAgQUNUID0gYygiVFJVRSIgPSAiYnJvd240IiwgIkZBTFNFIiA9ImtoYWtpIiksCiAgICBjdEROQS5CYXNlID0gYygiUE9TSVRJVkUiID0gInJlZDMiLCAiTkVHQVRJVkUiID0iYmx1ZSIpLAogICAgY3RETkEuQzJEMSA9IGMoIlBPU0lUSVZFIiA9ICJyZWQzIiwgIk5FR0FUSVZFIiA9ImJsdWUiKSwKICAgIGN0RE5BLnBvc3ROQUMgPSBjKCJQT1NJVElWRSIgPSAicmVkMyIsICJORUdBVElWRSIgPSJibHVlIiksCiAgICBjdEROQS5NUkQgPSBjKCJQT1NJVElWRSIgPSAicmVkMyIsICJORUdBVElWRSIgPSJibHVlIiksCiAgICBjdEROQS5zdXJ2ZWlsbGFuY2UgPSBjKCJQT1NJVElWRSIgPSAicmVkMyIsICJORUdBVElWRSIgPSJibHVlIiksCiAgICBERlMuRXZlbnQgPSBjKCJUUlVFIiA9ICJyZWQzIiwgIkZBTFNFIiA9ImJsdWUiKSwKICAgIE9TLkV2ZW50ID0gYygiVFJVRSIgPSAiYmxhY2siLCAiRkFMU0UiID0iZ3JheSIpCikKKQpodCA8LSBIZWF0bWFwKG1hdHJpeChucm93ID0gMCwgbmNvbCA9IGxlbmd0aChjaXJjX2RhdGEkU3RhZ2UpKSxzaG93X3Jvd19uYW1lcyA9IEZBTFNFLGNsdXN0ZXJfcm93cyA9IEYsY2x1c3Rlcl9jb2x1bW5zID0gRkFMU0UsIHRvcF9hbm5vdGF0aW9uID0gaGEpCnBkZigiaGVhdG1hcC5wZGYiLHdpZHRoID0gNywgaGVpZ2h0ID0gNykKZHJhdyhodCwgYW5ub3RhdGlvbl9sZWdlbmRfc2lkZSA9ICJib3R0b20iKQpkZXYub2ZmKCkKYGBgCgoKI092ZXJ2aWV3IFBsb3QKYGBge3J9CnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjbGluc3RhZ2U8LSByZWFkLmNzdigiUExBR0FTVF9PUC5jc3YiKQpjbGluc3RhZ2VfZGY8LSBhcy5kYXRhLmZyYW1lKGNsaW5zdGFnZSkKCiNEaXNwbGF5IHRoZSBzd2ltbWVyIHBsb3Qgd2l0aCB0aGUgbGFiZWwgYm94Cm9wbG90PC1zd2ltbWVyX3Bsb3QoZGY9Y2xpbnN0YWdlX2RmLAogICAgICAgICAgICAgICAgICAgIGlkPSdQYXRpZW50TmFtZScsCiAgICAgICAgICAgICAgICAgICAgZW5kPSdmdS5kaWZmLm1vbnRocycsCiAgICAgICAgICAgICAgICAgICAgZmlsbD0nZ3JheScsCiAgICAgICAgICAgICAgICAgICAgd2lkdGg9LjAxLCkKb3Bsb3QgPC0gb3Bsb3QgKyB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCkpCm9wbG90IDwtIG9wbG90ICsgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMTIsIDk2LCBieSA9IDYpKQpvcGxvdCA8LSBvcGxvdCArIGxhYnMoeCA9IlBhdGllbnRzIiAsIHk9Ik1vbnRocyBmcm9tIFN1cmdlcnkiKQpvcGxvdAoKCiMjcGxvdCBldmVudHMKb3Bsb3RfZXYxIDwtIG9wbG90ICsgc3dpbW1lcl9wb2ludHMoZGZfcG9pbnRzPWNsaW5zdGFnZV9kZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ9J1BhdGllbnROYW1lJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZT0nZGF0ZS5kaWZmLm1vbnRocycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVfc2hhcGUgPSdFdmVudF90eXBlJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZV9jb2wgPSAnRXZlbnQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTMuNSxmaWxsPSdibGFjaycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNjb2w9J2RhcmtncmVlbicKKQpvcGxvdF9ldjEKCiNTaGFwZSBjdXN0b21pemF0aW9uIHRvIEV2ZW50X3R5cGUKCm9wbG90X2V2MS4xIDwtIG9wbG90X2V2MSArIGdncGxvdDI6OnNjYWxlX3NoYXBlX21hbnVhbChuYW1lPSJFdmVudF90eXBlIix2YWx1ZXM9YygxLDE2LDYsMTgsNCksYnJlYWtzPWMoJ2N0RE5BX25lZycsJ2N0RE5BX3BvcycsJ0ltYWdpbmcnLCdTdXJnZXJ5JywnRGVhdGgnKSkKCm9wbG90X2V2MS4xCgojcGxvdCB0cmVhdG1lbnQKCm9wbG90X2V2MiA8LSBvcGxvdF9ldjEuMSArIHN3aW1tZXJfbGluZXMoZGZfbGluZXM9Y2xpbnN0YWdlX2RmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkPSdQYXRpZW50TmFtZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ9J1R4X3N0YXJ0Lm1vbnRocycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kPSdUeF9lbmQubW9udGhzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lX2NvbD0nVHhfdHlwZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT0zLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZV9hbHBoYSA9IDEuMCkKb3Bsb3RfZXYyIDwtIG9wbG90X2V2MiArIGd1aWRlcyhsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1LCBjb2xvciA9ICJibGFjayIpKSkKb3Bsb3RfZXYyICAKCgojY29sb3VyIGN1c3RvbWl6YXRpb24Kb3Bsb3RfZXYyLjIgPC0gb3Bsb3RfZXYyICsgZ2dwbG90Mjo6c2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IkV2ZW50Iix2YWx1ZXM9YyggInB1cnBsZSIsImJsYWNrIiwiYmxhY2siLCAibGlnaHRibHVlIiwgImdyZWVuIiwgInJlZCIsICJibHVlIiwib3JhbmdlIikpCm9wbG90X2V2Mi4yCmBgYAoKCiNSRlMgYnkgY3RETkEgYXQgQmFzZWxpbmUgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuQmFzZSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQmFzZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgQmFzZWxpbmUgfCBBbGwgcHRzIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLkJhc2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5CYXNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQmFzZSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojT1MgYnkgY3RETkEgYXQgQmFzZWxpbmUgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLkJhc2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5CYXNlLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIEJhc2VsaW5lIHwgQWxsIHB0cyIsIHlsYWI9ICJPdmVyYWxsLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS5CYXNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQmFzZSwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkJhc2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI1JGUyBieSBjdEROQSBsZXZlbHMgYXQgQmFzZWxpbmUgYmFzZWQgb24gQVVDIG9wdGltYWwgTVRNL21sIGxldmVsIC0gY3RETkEgQmFzZWxpbmUgcG9zaXRpdmUKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2U9PSJQT1NJVElWRSIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiNERlMuRXZlbnQKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjb21wbGV0ZS5jYXNlcyhjaXJjX2RhdGEkREZTLkV2ZW50LCBjaXJjX2RhdGEkY3RETkEuQmFzZS5NVE0pLF0KY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNIDwtIGFzLm51bWVyaWMoY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKQpST0MgPC0gcm9jKERGUy5FdmVudCB+ICBjdEROQS5CYXNlLk1UTSwgZGF0YSA9IGNpcmNfZGF0YSwgY2kgPSBUUlVFKQpwPC1nZ3JvYyhST0MsCiAgICAgICAgIGFlcyA9IGMoImxpbmV0eXBlIiksIGNvbG9yID0gImJsdWUiLCAgc2l6ZSA9IDEsCiAgICAgICAgIGxlZ2FjeS5heGVzID0gVFJVRSkgKwogIGdlb21fYWJsaW5lKGNvbG9yID0gImRhcmsgZ3JleSIsIHNpemUgPSAwLjUpICsKICB0aGVtZV9jbGFzc2ljKCkrCiAgeWxhYigiU2Vuc2l0aXZpdHkiKSArIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTE0KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTQpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIHNpemU9MTQpLGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xNCksbGVnZW5kLnRpdGxlICA9IGVsZW1lbnRfYmxhbmsoKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkKcAoKI0FVQwpBVUMgPC0gYXVjKFJPQykKcHJpbnQoQVVDKQpBVUNfY29uZiA8LSBjaS5hdWMoUk9DKQpwcmludChBVUNfY29uZikKcmVzLnJvYyA8LSByb2MoY2lyY19kYXRhJERGUy5FdmVudCwgY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKQpwbG90LnJvYyhyZXMucm9jLCBwcmludC5hdWMgPSBUUlVFLCBwcmludC50aHJlcyA9ICJiZXN0IikKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2U9PSJQT1NJVElWRSIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGJhc2VkIG9uIHRoZXNlIHF1YXJ0aWxlcwpjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS42bU1UTS5RID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZS5NVE0gPCAxLjA4NSB+IDEsCiAgICBjdEROQS5CYXNlLk1UTSA+PSAxLjA4NSB+IDIKICApKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS42bU1UTS5RLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgTVRNL21MIGdyb3VwcyBhdCBCYXNlbGluZSIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiTVRNL21MPDEuMDg1IiwgIk1UTS9tTOKJpTEuMDg1IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEsIGxldmVscz1jKCIxIiwiMiIpLCBsYWJlbHMgPSBjKCJNVE0vbUw8MS4wODUiLCAiTVRNL21M4omlMS4wODUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLjZtTVRNLlEsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKI09TIGJ5IGN0RE5BIGxldmVscyBhdCBCYXNlbGluZSBiYXNlZCBvbiBBVUMgb3B0aW1hbCBNVE0vbUwgbGV2ZWwgZnJvbSBSRlMgbW9kZWwgLSBjdEROQSBCYXNlbGluZSBwb3NpdGl2ZQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2UhPSIiLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZT09IlBPU0lUSVZFIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKIyBDcmVhdGUgYSBuZXcgdmFyaWFibGUgYmFzZWQgb24gdGhlc2UgcXVhcnRpbGVzCgpjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSA8LSBOQQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS42bU1UTS5RID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZS5NVE0gPCAxLjA4NSB+IDEsCiAgICBjdEROQS5CYXNlLk1UTSA+PSAxLjA4NSB+IDIKICApKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLjZtTVRNLlEsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIE1UTS9tTCBncm91cHMgYXQgQmFzZWxpbmUiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJNVE0vbUw8MS4wODUiLCAiTVRNL21M4omlMS4wODUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS42bU1UTS5RIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSwgbGV2ZWxzPWMoIjEiLCIyIiksIGxhYmVscyA9IGMoIk1UTS9tTDwxLjA4NSIsICJNVE0vbUziiaUxLjA4NSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuNm1NVE0uUSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgojUkZTIGJ5IGN0RE5BIGF0IEJhc2VsaW5lIC0gZXhjbHVkaW5nIHB0cyB0aGF0IGRpZCBub3QgcmVjZWl2ZSBOQUMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSROQUM9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5CYXNlLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5CYXNlLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBCYXNlbGluZSB8IE5BQyB0cmVhdGVkIG9ubHkiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQmFzZSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkJhc2UsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5CYXNlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCiNPUyBieSBjdEROQSBhdCBCYXNlbGluZSAtIGV4Y2x1ZGluZyBwdHMgdGhhdCBkaWQgbm90IHJlY2VpdmUgTkFDCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkTkFDPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLkJhc2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5CYXNlLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIEJhc2VsaW5lIHwgTkFDIHRyZWF0ZWQgb25seSIsIHlsYWI9ICJPdmVyYWxsLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS5CYXNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQmFzZSwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkJhc2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI1JGUyBieSBjdEROQSBsZXZlbHMgYXQgQmFzZWxpbmUgYmFzZWQgb24gQVVDIG9wdGltYWwgTVRNL21sIGxldmVsIC0gY3RETkEgQmFzZWxpbmUgcG9zaXRpdmUgZXhjbHVkaW5nIHB0cyB0aGF0IGRpZCBub3QgcmVjZWl2ZSBOQUMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSROQUM9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2U9PSJQT1NJVElWRSIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiNERlMuRXZlbnQKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjb21wbGV0ZS5jYXNlcyhjaXJjX2RhdGEkREZTLkV2ZW50LCBjaXJjX2RhdGEkY3RETkEuQmFzZS5NVE0pLF0KY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNIDwtIGFzLm51bWVyaWMoY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKQpST0MgPC0gcm9jKERGUy5FdmVudCB+ICBjdEROQS5CYXNlLk1UTSwgZGF0YSA9IGNpcmNfZGF0YSwgY2kgPSBUUlVFKQpwPC1nZ3JvYyhST0MsCiAgICAgICAgIGFlcyA9IGMoImxpbmV0eXBlIiksIGNvbG9yID0gImJsdWUiLCAgc2l6ZSA9IDEsCiAgICAgICAgIGxlZ2FjeS5heGVzID0gVFJVRSkgKwogIGdlb21fYWJsaW5lKGNvbG9yID0gImRhcmsgZ3JleSIsIHNpemUgPSAwLjUpICsKICB0aGVtZV9jbGFzc2ljKCkrCiAgeWxhYigiU2Vuc2l0aXZpdHkiKSArIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTE0KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTQpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIHNpemU9MTQpLGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xNCksbGVnZW5kLnRpdGxlICA9IGVsZW1lbnRfYmxhbmsoKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkKcAoKI0FVQwpBVUMgPC0gYXVjKFJPQykKcHJpbnQoQVVDKQpBVUNfY29uZiA8LSBjaS5hdWMoUk9DKQpwcmludChBVUNfY29uZikKcmVzLnJvYyA8LSByb2MoY2lyY19kYXRhJERGUy5FdmVudCwgY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKQpwbG90LnJvYyhyZXMucm9jLCBwcmludC5hdWMgPSBUUlVFLCBwcmludC50aHJlcyA9ICJiZXN0IikKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSROQUM9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2U9PSJQT1NJVElWRSIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGJhc2VkIG9uIHRoZXNlIHF1YXJ0aWxlcwpjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS42bU1UTS5RID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZS5NVE0gPCAwLjcxIH4gMSwKICAgIGN0RE5BLkJhc2UuTVRNID49IDAuNzEgfiAyCiAgKSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIE1UTS9tTCBncm91cHMgYXQgQmFzZWxpbmUiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIk1UTS9tTDwwLjcxIiwgIk1UTS9tTOKJpTAuNzEiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS42bU1UTS5RIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSwgbGV2ZWxzPWMoIjEiLCIyIiksIGxhYmVscyA9IGMoIk1UTS9tTDwwLjcxIiwgIk1UTS9tTOKJpTAuNzEiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLjZtTVRNLlEsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKI1JGUyBieSBjdEROQSBvbi1OQVQgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzJEMSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuQzJEMSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgc3RhdHVzIG9uLU5BVCB8IEFsbCBwdHMiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkMyRDEsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCiNPUyBieSBjdEROQSBvbi1OQVQgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzJEMSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLkMyRDEsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIHN0YXR1cyBvbi1OQVQgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLkMyRDEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojREZTIGJ5IGN0RE5BIENsZWFyYW5jZSBkdXJpbmcgTkFUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5DMkQxLkNsZWFyYW5jZSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiB+ICJUUlVFIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiB+ICJGQUxTRSIsCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoInJlZCIsImJsdWUiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIGNsZWFyYW5jZSBDMkQxIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIFN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJObyBDbGVhcmFuY2UiLCAiQ2xlYXJhbmNlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNPUyBieSBjdEROQSBDbGVhcmFuY2UgZHVyaW5nIE5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuQzJEMS5DbGVhcmFuY2UgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJORUdBVElWRSIgfiAiVFJVRSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgfiAiRkFMU0UiLAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoInJlZCIsImJsdWUiKSwgdGl0bGU9Ik9TIC0gY3RETkEgY2xlYXJhbmNlIEMyRDEiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIFN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJObyBDbGVhcmFuY2UiLCAiQ2xlYXJhbmNlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNSRlMgYnkgY3RETkEgcG9zdC1OQVQgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEucG9zdE5BQywgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgc3RhdHVzIHBvc3QtTkFUIHwgQWxsIHB0cyIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS5wb3N0TkFDIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucG9zdE5BQywgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLnBvc3ROQUMsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI09TIGJ5IGN0RE5BIHBvc3QtTkFUIC0gYWxsIHN0YWdlcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5wb3N0TkFDLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBzdGF0dXMgcG9zdC1OQVQgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQywgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojTXVsdGl2YXJpYXRlIGNveCByZWdyZXNzaW9uIGZvciBSRlMgLSBjdEROQSBwb3N0LU5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEucG9zdE5BQyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIiksIGxhYmVscyA9IGMoIk5lZ2F0aXZlIiwgIlBvc2l0aXZlIikpCmNpcmNfZGF0YSRQcmltU2l0ZSA8LSBmYWN0b3IoY2lyY19kYXRhJFByaW1TaXRlLCBsZXZlbHM9YygiU3RvbWFjaCIsIkcvSiIpKQpjaXJjX2RhdGEkR2VuZGVyIDwtIGZhY3RvcihjaXJjX2RhdGEkR2VuZGVyLCBsZXZlbHM9YygiTWFsZSIsIkZlbWFsZSIpKQpjaXJjX2RhdGEkQWdlLkdyb3VwIDwtIGZhY3RvcihjaXJjX2RhdGEkQWdlLkdyb3VwLCBsZXZlbHM9YygiMiIsIjEiKSwgbGFiZWxzID0gYygiPjcwIiwgIuKJpDcwIikpCmNpcmNfZGF0YSRwVC5TdGFnZSA8LSBmYWN0b3IoY2lyY19kYXRhJHBULlN0YWdlLCBsZXZlbHM9YygiVDEtVDMiLCJUNCIpKQpjaXJjX2RhdGEkeXBOU3RhdHVzIDwtIGZhY3RvcihjaXJjX2RhdGEkeXBOU3RhdHVzLCBsZXZlbHM9YygiTjAiLCJOMS1OMyIpKQpjaXJjX2RhdGEkVFJHIDwtIGZhY3RvcihjaXJjX2RhdGEkVFJHLCBsZXZlbHM9YygiVFJHMS8yLzMiLCJUUkc0LzUiKSkKY2lyY19kYXRhJEFDVCA8LSBmYWN0b3IoY2lyY19kYXRhJEFDVCwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpLCBsYWJlbHMgPSBjKCJZZXMiLCAiTm8iKSkKc3Vydl9vYmplY3QgPC0gU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkgCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5wb3N0TkFDICsgUHJpbVNpdGUgKyBHZW5kZXIgKyBBZ2UuR3JvdXAgKyBBQ1QsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCwgZGF0YSA9IGNpcmNfZGF0YSwgbWFpbiA9ICJNdWx0aXZhcmlhdGUgUmVncmVzc2lvbiBNb2RlbCBmb3IgUkZTIiwgcmVmTGFiZWwgPSAiUmVmZXJlbmNlIEdyb3VwIikKdGVzdC5waCA8LSBjb3guenBoKGNveF9maXQpCmBgYAoKCiNNdWx0aXZhcmlhdGUgY294IHJlZ3Jlc3Npb24gZm9yIE9TIC0gY3RETkEgcG9zdC1OQVQKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5wb3N0TkFDIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJOZWdhdGl2ZSIsICJQb3NpdGl2ZSIpKQpjaXJjX2RhdGEkUHJpbVNpdGUgPC0gZmFjdG9yKGNpcmNfZGF0YSRQcmltU2l0ZSwgbGV2ZWxzPWMoIlN0b21hY2giLCJHL0oiKSkKY2lyY19kYXRhJEdlbmRlciA8LSBmYWN0b3IoY2lyY19kYXRhJEdlbmRlciwgbGV2ZWxzPWMoIk1hbGUiLCJGZW1hbGUiKSkKY2lyY19kYXRhJEFnZS5Hcm91cCA8LSBmYWN0b3IoY2lyY19kYXRhJEFnZS5Hcm91cCwgbGV2ZWxzPWMoIjIiLCIxIiksIGxhYmVscyA9IGMoIj43MCIsICLiiaQ3MCIpKQpjaXJjX2RhdGEkcFQuU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRwVC5TdGFnZSwgbGV2ZWxzPWMoIlQxLVQzIiwiVDQiKSkKY2lyY19kYXRhJHlwTlN0YXR1cyA8LSBmYWN0b3IoY2lyY19kYXRhJHlwTlN0YXR1cywgbGV2ZWxzPWMoIk4wIiwiTjEtTjMiKSkKY2lyY19kYXRhJFRSRyA8LSBmYWN0b3IoY2lyY19kYXRhJFRSRywgbGV2ZWxzPWMoIlRSRzEvMi8zIiwiVFJHNC81IikpCmNpcmNfZGF0YSRBQ1QgPC0gZmFjdG9yKGNpcmNfZGF0YSRBQ1QsIGxldmVscz1jKCJUUlVFIiwiRkFMU0UiKSwgbGFiZWxzID0gYygiWWVzIiwgIk5vIikpCnN1cnZfb2JqZWN0IDwtIFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KSAKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLnBvc3ROQUMgKyBQcmltU2l0ZSArIEdlbmRlciArIEFnZS5Hcm91cCArIEFDVCwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LCBkYXRhID0gY2lyY19kYXRhLCBtYWluID0gIk11bHRpdmFyaWF0ZSBSZWdyZXNzaW9uIE1vZGVsIGZvciBPUyIsIHJlZkxhYmVsID0gIlJlZmVyZW5jZSBHcm91cCIpCnRlc3QucGggPC0gY294LnpwaChjb3hfZml0KQpgYGAKCgojUkZTIGJ5IGN0RE5BIENsZWFyYW5jZSBwb3N0LU5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuQzJEMS5DbGVhcmFuY2UgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiVFJVRSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgfiAiRkFMU0UiLAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJyZWQiLCJibHVlIiksIHRpdGxlPSJSRlMgLSBjdEROQSBjbGVhcmFuY2UgcG9zdC1OQVQiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gU3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIk5vIENsZWFyYW5jZSIsICJDbGVhcmFuY2UiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBsZXZlbHM9YygiVFJVRSIsIkZBTFNFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKI09TIGJ5IGN0RE5BIENsZWFyYW5jZSBwb3N0LU5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuQzJEMS5DbGVhcmFuY2UgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiVFJVRSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgfiAiRkFMU0UiLAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoInJlZCIsImJsdWUiKSwgdGl0bGU9Ik9TIC0gY3RETkEgY2xlYXJhbmNlIHBvc3QtTkFUIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBTdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiTm8gQ2xlYXJhbmNlIiwgIkNsZWFyYW5jZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLkMyRDEuQ2xlYXJhbmNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UsIGxldmVscz1jKCJUUlVFIiwiRkFMU0UiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgojQXNzb2NpYXRpb24gb2YgY3RETkEgRHluYW1pY3MgcG9zdC1OQVQgYW5kIFJlc3BvbnNlCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5EeW5hbWljcyA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLy0vLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8rLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiIH4gImN0RE5BICsvKy8rIgogICkpCgojVmVydGljYWwgRmlzaGVyIHBsb3QgZm9yIGN0RE5BIGNsZWFyYW5jZSBwb3N0LU5BVCBhbmQgUmVjIFN0YXR1cwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyE9IiIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvLS8tIiwgImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCmNpcmNfZGF0YSRUUkcgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkcsIGxldmVscyA9IGMoIlRSRzEvMi8zIiwgIlRSRzQvNSIpKQpjb250aW5nZW5jeV90YWJsZSA8LSB0YWJsZShjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MsIGNpcmNfZGF0YSRUUkcpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpjaGlfc3F1YXJlX3Rlc3QgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpX3NxdWFyZV90ZXN0KQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmJFRvdGFsIDwtIGF2ZSh0YWJsZV9kZiRGcmVxLCB0YWJsZV9kZiRWYXIxLCBGVU4gPSBzdW0pCnRhYmxlX2RmJFBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkRnJlcSAvIHRhYmxlX2RmJFRvdGFsCnRhYmxlX2RmJE1pZGRsZVBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkUGVyY2VudGFnZSAvIDIKCiMgU3dhcHBpbmcgeCBhbmQgeSBpbiBnZ3Bsb3QgZnVuY3Rpb24gdG8gbWFrZSBiYXIgcGxvdCB2ZXJ0aWNhbApnZ3Bsb3QodGFibGVfZGYsIGFlcyh5ID0gVmFyMSwgeCA9IFBlcmNlbnRhZ2UsIGZpbGwgPSBWYXIyKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gTWlkZGxlUGVyY2VudGFnZSwgbGFiZWwgPSBGcmVxKSwgcG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIsIHZqdXN0ID0gMS41LCBzaXplID0gNykgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJjdEROQSBEeW1hbWljcyBwb3N0LU5BVCIsIHkgPSAiY3RETkEiLCB4ID0gIlBhdGllbnRzICglKSIsIGZpbGwgPSAiUGF0aCBSZXNwb25zZSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVFJHMS8yLzMiID0gImxpZ2h0Ymx1ZTMiLCAiVFJHNC81IiA9ICJyZWQiKSkgKyAjIGRlZmluZSBjdXN0b20gY29sb3JzCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEuNSwgc2l6ZSA9IDE0KSwgIyBpbmNyZWFzZSB5LWF4aXMgdGV4dCBzaXplCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHgtYXhpcyB0ZXh0IHNpemUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHktYXhpcyBsYWJlbCBzaXplCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB4LWF4aXMgbGFiZWwgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSkgICMgaW5jcmVhc2UgUmVjdXJyZW5jZSBsYWJlbCBzaXplCgojQ2FsY3VsYXRpbmcgcC12YWx1ZSB3aXRoIEZpc2hlciBleGFjdCB0ZXN0IGZvciB0aGUgY3RETkEgKy8rLysgdnMgY3RETkEgKy8rLy0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuRHluYW1pY3MgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJORUdBVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8tLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvKy8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiB+ICJjdEROQSArLysvKyIKICApKQoKI1ZlcnRpY2FsIEZpc2hlciBwbG90IGZvciBjdEROQSBjbGVhcmFuY2UgcG9zdC1OQVQgYW5kIFJlYyBTdGF0dXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MhPSIiLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MhPSJjdEROQSArLy0vLSIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCmNpcmNfZGF0YSRUUkcgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkcsIGxldmVscyA9IGMoIlRSRzEvMi8zIiwgIlRSRzQvNSIpKQpjb250aW5nZW5jeV90YWJsZSA8LSB0YWJsZShjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MsIGNpcmNfZGF0YSRUUkcpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpjaGlfc3F1YXJlX3Rlc3QgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpX3NxdWFyZV90ZXN0KQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCmBgYAoKCiNBc3NvY2lhdGlvbiBvZiBjdEROQSBEeW5hbWljcyBwb3N0LU5BVCBhbmQgUmVzcG9uc2UgVjIgKFRSRzEvMiB2cyBUUkczLTUpCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5EeW5hbWljcyA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLy0vLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8rLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiIH4gImN0RE5BICsvKy8rIgogICkpCgojVmVydGljYWwgRmlzaGVyIHBsb3QgZm9yIGN0RE5BIGNsZWFyYW5jZSBwb3N0LU5BVCBhbmQgUmVjIFN0YXR1cwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyE9IiIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvLS8tIiwgImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCmNpcmNfZGF0YSRUUkd2MiA8LSBmYWN0b3IoY2lyY19kYXRhJFRSR3YyLCBsZXZlbHMgPSBjKCJUUkcxLzIiLCAiVFJHMy80LzUiKSkKY29udGluZ2VuY3lfdGFibGUgPC0gdGFibGUoY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzLCBjaXJjX2RhdGEkVFJHdjIpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpjaGlfc3F1YXJlX3Rlc3QgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpX3NxdWFyZV90ZXN0KQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmJFRvdGFsIDwtIGF2ZSh0YWJsZV9kZiRGcmVxLCB0YWJsZV9kZiRWYXIxLCBGVU4gPSBzdW0pCnRhYmxlX2RmJFBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkRnJlcSAvIHRhYmxlX2RmJFRvdGFsCnRhYmxlX2RmJE1pZGRsZVBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkUGVyY2VudGFnZSAvIDIKCiMgU3dhcHBpbmcgeCBhbmQgeSBpbiBnZ3Bsb3QgZnVuY3Rpb24gdG8gbWFrZSBiYXIgcGxvdCB2ZXJ0aWNhbApnZ3Bsb3QodGFibGVfZGYsIGFlcyh5ID0gVmFyMSwgeCA9IFBlcmNlbnRhZ2UsIGZpbGwgPSBWYXIyKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gTWlkZGxlUGVyY2VudGFnZSwgbGFiZWwgPSBGcmVxKSwgcG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIsIHZqdXN0ID0gMS41LCBzaXplID0gNykgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJjdEROQSBEeW1hbWljcyBwb3N0LU5BVCIsIHkgPSAiY3RETkEiLCB4ID0gIlBhdGllbnRzICglKSIsIGZpbGwgPSAiUGF0aCBSZXNwb25zZSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVFJHMS8yIiA9ICJsaWdodGJsdWUzIiwgIlRSRzMvNC81IiA9ICJyZWQiKSkgKyAjIGRlZmluZSBjdXN0b20gY29sb3JzCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEuNSwgc2l6ZSA9IDE0KSwgIyBpbmNyZWFzZSB5LWF4aXMgdGV4dCBzaXplCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHgtYXhpcyB0ZXh0IHNpemUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHktYXhpcyBsYWJlbCBzaXplCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB4LWF4aXMgbGFiZWwgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSkgICMgaW5jcmVhc2UgUmVjdXJyZW5jZSBsYWJlbCBzaXplCgojQ2FsY3VsYXRpbmcgcC12YWx1ZSB3aXRoIEZpc2hlciBleGFjdCB0ZXN0IGZvciB0aGUgY3RETkEgKy8rLysgdnMgY3RETkEgKy8rLy0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuRHluYW1pY3MgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJORUdBVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8tLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvKy8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiB+ICJjdEROQSArLysvKyIKICApKQoKI1ZlcnRpY2FsIEZpc2hlciBwbG90IGZvciBjdEROQSBjbGVhcmFuY2UgcG9zdC1OQVQgYW5kIFJlYyBTdGF0dXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MhPSIiLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MhPSJjdEROQSArLy0vLSIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCmNpcmNfZGF0YSRUUkd2MiA8LSBmYWN0b3IoY2lyY19kYXRhJFRSR3YyLCBsZXZlbHMgPSBjKCJUUkcxLzIiLCAiVFJHMy80LzUiKSkKY29udGluZ2VuY3lfdGFibGUgPC0gdGFibGUoY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzLCBjaXJjX2RhdGEkVFJHdjIpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpjaGlfc3F1YXJlX3Rlc3QgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpX3NxdWFyZV90ZXN0KQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCmBgYAoKCiNSRlMgYnkgY3RETkEgRHluYW1pY3MgcG9zdC1OQVQKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQoKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLkR5bmFtaWNzID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiTkVHQVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvLS8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLysvLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgfiAiY3RETkEgKy8rLysiCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5EeW5hbWljcywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgRHluYW1pY3MgcG9zdC1OQVQiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BICsvLS8tIiwiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MsIGxldmVscz1jKCJjdEROQSArLy0vLSIsImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5EeW5hbWljcywgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKYGBgCgoKI09TIGJ5IGN0RE5BIER5bmFtaWNzIHBvc3QtTkFUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5EeW5hbWljcyA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLy0vLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8rLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiIH4gImN0RE5BICsvKy8rIgogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuRHluYW1pY3MsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5EeW5hbWljcywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBEeW5hbWljcyBwb3N0LU5BVCIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BICsvLS8tIiwiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MsIGxldmVscz1jKCJjdEROQSArLy0vLSIsImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCmNveF9maXQgPC0gY294cGhmKHN1cnZfb2JqZWN0IH4gY3RETkEuRHluYW1pY3MsIGRhdGE9Y2lyY19kYXRhKQpzdW1tYXJ5KGNveF9maXQpCmBgYAoKCiNMZXZlbHMgb2YgQmFzZWxpbmUgTVRNL21MIGluIGN0RE5BIER5bmFtaWNzIHBvc3QtTkFUIGNhdGVnb3JpZXMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5EeW5hbWljcyA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLy0vLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8rLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiIH4gImN0RE5BICsvKy8rIgogICkpCgojIFRyYW5zZm9ybSBjdEROQS5CYXNlLk1UTSB3aXRoIGxvZzEwCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCAhaXMubmEoY3RETkEuRHluYW1pY3MpKQpjaXJjX2RhdGEkY3RETkEuQmFzZS5NVE0gPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKSkKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MsIGxldmVscz1jKCJjdEROQSArLy0vLSIsImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIikpCm1lZGlhbl9CYXNlX01UTSA8LSBhZ2dyZWdhdGUoY3RETkEuQmFzZS5NVE0gfiBjdEROQS5EeW5hbWljcywgZGF0YSA9IGNpcmNfZGF0YSwgRlVOID0gbWVkaWFuKQpwcmludChtZWRpYW5fQmFzZV9NVE0pCgojIENyZWF0ZSB2aW9saW4gcGxvdCB3aXRoIGxvZzEwIHNjYWxlIG9uIHktYXhpcwpnZ3Bsb3QoY2lyY19kYXRhLCBhZXMoeD1jdEROQS5EeW5hbWljcywgeT1jdEROQS5CYXNlLk1UTSwgZmlsbD1jdEROQS5EeW5hbWljcykpICsKICBnZW9tX3Zpb2xpbih0cmltPUZBTFNFKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoImN0RE5BICsvLS8tIj0ibGlnaHRibHVlIiwgImN0RE5BICsvKy8tIj0ibGlnaHRncmVlbiIsICJjdEROQSArLysvKyI9InNhbG1vbiIpKSArCiAgZ2VvbV9ib3hwbG90KHdpZHRoPTAuMSwgZmlsbD0id2hpdGUiLCBjb2xvdXI9ImJsYWNrIiwgYWxwaGE9MC41KSArCiAgc2NhbGVfeV9sb2cxMChicmVha3M9YygwLjAwMSwgMC4wMSwgMC4xLCAxLCAxMCwgMTAwLCAxMDAwLCAxMDAwMCkpICsKICBsYWJzKHRpdGxlPSJCYXNlbGluZSBNVE0vbUwgfCBEeW5hbWljcyBwb3N0LU5BVCIsIHg9IkR5bmFtaWNzIHBvc3QtTkFUIiwgeT0iQmFzZWxpbmUgTVRNL21MIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKbTNfMXYyIDwtIHdpbGNveC50ZXN0KGN0RE5BLkJhc2UuTVRNIH4gY3RETkEuRHluYW1pY3MsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyAlaW4lIGMoImN0RE5BICsvLS8tIiwgImN0RE5BICsvKy8tIiksIF0sCiAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpCnByaW50KG0zXzF2MikKbTNfMXYzIDwtIHdpbGNveC50ZXN0KGN0RE5BLkJhc2UuTVRNIH4gY3RETkEuRHluYW1pY3MsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyAlaW4lIGMoImN0RE5BICsvLS8tIiwgImN0RE5BICsvKy8rIiksIF0sCiAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpCnByaW50KG0zXzF2MykKbTNfMnYzIDwtIHdpbGNveC50ZXN0KGN0RE5BLkJhc2UuTVRNIH4gY3RETkEuRHluYW1pY3MsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyAlaW4lIGMoImN0RE5BICsvKy8tIiwgImN0RE5BICsvKy8rIiksIF0sCiAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpCnByaW50KG0zXzJ2MykKYGBgCgojVGltZSBvZiBjdEROQSBkcmF3cyBhdCB0aGUgTVJEIHdpbmRvdyBmcm9tIHN1cmdlcnkKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQgPT0gVFJVRSwgXQoKY2lyY19kYXRhJGN0RE5BLk1SRC5EYXRlIDwtIGFzLkRhdGUoY2lyY19kYXRhJGN0RE5BLk1SRC5EYXRlLCBmb3JtYXQ9IiVtLyVkLyVZIikKY2lyY19kYXRhJFN1cmdlcnkuRGF0ZSA8LSBhcy5EYXRlKGNpcmNfZGF0YSRTdXJnZXJ5LkRhdGUsIGZvcm1hdD0iJW0vJWQvJVkiKQpjaXJjX2RhdGEkVGltZV90b19jdEROQV9NUkQgPC0gYXMubnVtZXJpYyhkaWZmdGltZShjaXJjX2RhdGEkY3RETkEuTVJELkRhdGUsIGNpcmNfZGF0YSRTdXJnZXJ5LkRhdGUsIHVuaXRzPSJkYXlzIikpCm1lZGlhbl9jdEROQV9NUkQgPC0gbWVkaWFuKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX01SRCwgbmEucm09VFJVRSkKcmFuZ2VfY3RETkFfTVJEIDwtIHJhbmdlKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX01SRCwgbmEucm09VFJVRSkKUTFfY3RETkFfTVJEIDwtIHF1YW50aWxlKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX01SRCwgMC4yNSwgbmEucm09VFJVRSkKUTNfY3RETkFfTVJEIDwtIHF1YW50aWxlKGNpcmNfZGF0YSRUaW1lX3RvX2N0RE5BX01SRCwgMC43NSwgbmEucm09VFJVRSkKSVFSX2N0RE5BX01SRCA8LSBJUVIoY2lyY19kYXRhJFRpbWVfdG9fY3RETkFfTVJELCBuYS5ybT1UUlVFKQpjYXQoIk1lZGlhbiB0aW1lIGZyb20gc3VyZ2VyeSB0byBjdEROQSBNUkQgdGltZSBwb2ludDoiLCBtZWRpYW5fY3RETkFfTVJELCAiZGF5c1xuIikKY2F0KCJSYW5nZToiLCByYW5nZV9jdEROQV9NUkRbMV0sICItIiwgcmFuZ2VfY3RETkFfTVJEWzJdLCAiZGF5c1xuIikKY2F0KCJRMSAoMjV0aCBwZXJjZW50aWxlKToiLCBRMV9jdEROQV9NUkQsICJkYXlzXG4iKQpjYXQoIlEzICg3NXRoIHBlcmNlbnRpbGUpOiIsIFEzX2N0RE5BX01SRCwgImRheXNcbiIpCmNhdCgiSW50ZXJxdWFydGlsZSBSYW5nZSAoSVFSKToiLCBJUVJfY3RETkFfTVJELCAiZGF5c1xuIikKYGBgCgojUkZTIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93IC0gYWxsIHN0YWdlcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkREZTLm1vbnRocz1jaXJjX2RhdGEkREZTLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuTVJELCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIE1SRCB3aW5kb3cgfCBBbGwgcHRzIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5NUkQgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5NUkQsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI09TIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93IC0gYWxsIHN0YWdlcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkRlUubW9udGhzPWNpcmNfZGF0YSRGVS5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRGVS5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBNUkQgd2luZG93IHwgQWxsIHB0cyIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsIDI0KSkKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgoKI1JGUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAtIEFDVCBwdHMgb25seQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEFDVD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkREZTLm1vbnRocz1jaXJjX2RhdGEkREZTLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuTVJELCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIE1SRCB3aW5kb3cgfCBBQ1QgdHJlYXRlZCIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwgMjQpKQpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuTVJELCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCiNPUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAtIEFDVCBwdHMgb25seQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEFDVD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkRlUubW9udGhzPWNpcmNfZGF0YSRGVS5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRGVS5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBNUkQgd2luZG93IHwgQUNUIHRyZWF0ZWQiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5NUkQgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5NUkQsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKCiNSRlMgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgLSBOQUMgcHRzIG9ubHkKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSROQUM9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJERGUy5tb250aHM9Y2lyY19kYXRhJERGUy5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRERlMubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuTVJELCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBNUkQgd2luZG93IHwgTkFDIHRyZWF0ZWQiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsIDI0KSkKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojT1MgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgLSBOQUMgcHRzIG9ubHkKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSROQUM9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJEZVLm1vbnRocz1jaXJjX2RhdGEkRlUubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkRlUubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEIHdpbmRvdyB8IE5BQyB0cmVhdGVkIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwgMjQpKQpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuTVJELCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCgojUkZTIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93ICYgeXBUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YSRERlMubW9udGhzPWNpcmNfZGF0YSRERlMubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkREZTLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMSwKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDIsCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiAzLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIE1SRCAmIHlwVE4iLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwyNCkpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIxIiwiMiIsIjMiLCI0IiksIGxhYmVscyA9IGMoImN0RE5BKC0pICYgVDEtVDMiLCAiY3RETkEoKykgJiBUMS1UMyIsICJjdEROQSgtKSAmIFQ0IiwgImN0RE5BKCspICYgVDQiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCgojUmVwZWF0IGFuYWx5c2lzIHRvIGNvbXBhcmUgY3RETkEgTVJEICgtKSB2cyAoKykgaW4gVDQKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkREZTLm1vbnRocz1jaXJjX2RhdGEkREZTLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDEsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAyLAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gMywKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBNUkQgJiB5cFROIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEoLSkgJiBUMS1UMyIsICJjdEROQSgrKSAmIFQxLVQzIiwgImN0RE5BKC0pICYgVDQiLCAiY3RETkEoKykgJiBUNCIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMiIsIjQiLCIxIiwiMyIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhPWNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKYGBgCgojT1MgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgJiB5cFQKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJEZVLm1vbnRocz1jaXJjX2RhdGEkRlUubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkRlUubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuUmlzayA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5TdGFnZS5JSS5UTk0gPSBjYXNlX3doZW4oCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAxLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMiwKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDMsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiA0CiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSE9IiIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIE1SRCAmIHlwVE4iLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEoLSkgJiBUMS1UMyIsICJjdEROQSgrKSAmIFQxLVQzIiwgImN0RE5BKC0pICYgVDQiLCAiY3RETkEoKykgJiBUNCIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQoKI1JlcGVhdCBhbmFseXNpcyB0byBjb21wYXJlIGN0RE5BIHBvc3QtTkFUICgtKSB2cyAoKykgaW4gVDQKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkRlUubW9udGhzPWNpcmNfZGF0YSRGVS5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRGVS5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDEsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAyLAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gMywKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEICYgeXBUTiIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwyNCkpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIyIiwiNCIsIjEiLCIzIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpgYGAKCiNSRlMgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgJiB5cE4KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJERGUy5tb250aHM9Y2lyY19kYXRhJERGUy5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRERlMubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuUmlzayA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5TdGFnZS5JSS5UTk0gPSBjYXNlX3doZW4oCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMSwKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgeXBOU3RhdHVzID09ICJOMCIgfiAyLAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+IDMsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIE1SRCAmIHlwTiIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BKC0pICYgeXBOMCIsICJjdEROQSgrKSAmIHlwTjAiLCAiY3RETkEoLSkgJiB5cE4rIiwgImN0RE5BKCspICYgeXBOKyIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIHlwTjAiLCAiY3RETkEoKykgJiB5cE4wIiwgImN0RE5BKC0pICYgeXBOKyIsICJjdEROQSgrKSAmIHlwTisiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmBgYAoKI09TIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93ICYgeXBOCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YSRGVS5tb250aHM9Y2lyY19kYXRhJEZVLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEZVLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4wIiB+IDEsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMiwKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgeXBOU3RhdHVzID09ICJOMS1OMyIgfiAzLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEICYgeXBOIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BKC0pICYgeXBOMCIsICJjdEROQSgrKSAmIHlwTjAiLCAiY3RETkEoLSkgJiB5cE4rIiwgImN0RE5BKCspICYgeXBOKyIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIHlwTjAiLCAiY3RETkEoKykgJiB5cE4wIiwgImN0RE5BKC0pICYgeXBOKyIsICJjdEROQSgrKSAmIHlwTisiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmBgYAoKI1JGUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAmIFRSRyBjb21iaW5hdGlvbiBWMiAoVFJHMS8yIHZzIFRSRzMtNSkKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEkREZTLm1vbnRocz1jaXJjX2RhdGEkREZTLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkVFJHdjIgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkd2MiwgbGV2ZWxzID0gYygiVFJHMS8yIiwgIlRSRzMvNC81IikpCgpjaXJjX2RhdGEkY3RETkEucENSIDwtIE5BCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLnBDUiA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgVFJHdjIgPT0gIlRSRzEvMiIgfiAiMSIsCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIFRSR3YyID09ICJUUkczLzQvNSIgfiAiMiIsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIFRSR3YyID09ICJUUkczLzQvNSIgfiAiMyIKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVshaXMubmEoY2lyY19kYXRhJGN0RE5BLnBDUiksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEucENSLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsImdyZWVuIiwicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBNUkQvVFJHIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiVFJHMS8yIGN0RE5BICgtKSIsIlRSRzMvNC81IGN0RE5BICgtKSIsICJUUkczLzQvNSBjdEROQSAoKykiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBDUiwgbGV2ZWxzPWMoIjEiLCIyIiwiMyIpLCBsYWJlbHM9YygiVFJHMS8yIGN0RE5BICgtKSIsIlRSRzMvNC81IGN0RE5BICgtKSIsICJUUkczLzQvNSBjdEROQSAoKykiKSkKY294X2ZpdCA8LSBjb3hwaGYoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGE9Y2lyY19kYXRhKQpzdW1tYXJ5KGNveF9maXQpCmBgYAoKCiNPUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAmIFRSRyBjb21iaW5hdGlvbiBWMiAoVFJHMS8yIHZzIFRSRzMtNSkKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEkRlUubW9udGhzPWNpcmNfZGF0YSRGVS5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRGVS5tb250aHM+PTAsXQpjaXJjX2RhdGEkVFJHdjIgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkd2MiwgbGV2ZWxzID0gYygiVFJHMS8yIiwgIlRSRzMvNC81IikpCgpjaXJjX2RhdGEkY3RETkEucENSIDwtIE5BCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLnBDUiA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgVFJHdjIgPT0gIlRSRzEvMiIgfiAiMSIsCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIFRSR3YyID09ICJUUkczLzQvNSIgfiAiMiIsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIFRSR3YyID09ICJUUkczLzQvNSIgfiAiMyIKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVshaXMubmEoY2lyY19kYXRhJGN0RE5BLnBDUiksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEL1RSRyIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJUUkcxLzIgY3RETkEgKC0pIiwiVFJHMy80LzUgY3RETkEgKC0pIiwgIlRSRzMvNC81IGN0RE5BICgrKSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEucENSIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucENSLCBsZXZlbHM9YygiMSIsIjIiLCIzIiksIGxhYmVscz1jKCJUUkcxLzIgY3RETkEgKC0pIiwiVFJHMy80LzUgY3RETkEgKC0pIiwgIlRSRzMvNC81IGN0RE5BICgrKSIpKQpjb3hfZml0IDwtIGNveHBoZihzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKYGBgCgoKI1JGUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAmIHlwVE4gQ2hhcmFjdGVyaXN0aWNzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkID09IFRSVUUsXQpjaXJjX2RhdGEkREZTLm1vbnRocyA8LSBjaXJjX2RhdGEkREZTLm1vbnRocyAtIDMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkREZTLm1vbnRocyA+PSAwLF0KY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBOQQoKIyBEZWZpbmUgbmV3IGNhdGVnb3JpZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEucENSID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZT09IlQxLVQzIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gIjEiLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgfCBwVC5TdGFnZSA9PSAiVDQiIHwgeXBOU3RhdHVzID09ICJOMS1OMyIgfiAiMiIKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVshaXMubmEoY2lyY19kYXRhJGN0RE5BLnBDUiksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC0gU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSwgY29uZi5pbnQgPSAwLjk1LCBjb25mLnR5cGUgPSAibG9nLWxvZyIpCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIAogICAgICAgICAgIGJyZWFrLnRpbWUuYnkgPSAxMiwgcGFsZXR0ZSA9IGMoImJsdWUiLCAicmVkIiksIAogICAgICAgICAgIHRpdGxlID0gIlJGUyAtIGN0RE5BIE1SRC9DbGluaWNhbCBDaGFyYWN0ZXJpc3RpY3MiLCAKICAgICAgICAgICB5bGFiID0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWIgPSAiVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCAKICAgICAgICAgICBsZWdlbmQubGFicyA9IGMoIk1SRCBuZWcsIFQxLVQzLCBOMCIsICJNUkQgcG9zIG9yIFQ0IG9yIE4xLU4zIiksIAogICAgICAgICAgIGxlZ2VuZC50aXRsZSA9ICIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcyA9IGMoMCwgMjQpKQpjaXJjX2RhdGEkY3RETkEucENSIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucENSLCBsZXZlbHM9YygiMSIsIjIiKSwgbGFiZWxzPWMoIk1SRCBuZWcsIFQxLVQzLCBOMCIsIk1SRCBwb3Mgb3IgVDQgb3IgTjEtTjMiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCiNPUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAmIHlwVE4gQ2hhcmFjdGVyaXN0aWNzCmBgYHtyfQojIENsZWFyIHdvcmtzcGFjZSBhbmQgc2V0IHdvcmtpbmcgZGlyZWN0b3J5CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQgPT0gVFJVRSxdCmNpcmNfZGF0YSRGVS5tb250aHMgPC0gY2lyY19kYXRhJEZVLm1vbnRocyAtIDMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkRlUubW9udGhzID49IDAsXQpjaXJjX2RhdGEkY3RETkEucENSIDwtIE5BCgojIERlZmluZSBuZXcgY2F0ZWdvcmllcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5wQ1IgPSBjYXNlX3doZW4oCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlPT0iVDEtVDMiICYgeXBOU3RhdHVzID09ICJOMCIgfiAiMSIsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiB8IHBULlN0YWdlID09ICJUNCIgfCB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+ICIyIgogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEucENSKSxdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC0gU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEsIGNvbmYuaW50ID0gMC45NSwgY29uZi50eXBlID0gImxvZy1sb2ciKQpnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCAKICAgICAgICAgICBicmVhay50aW1lLmJ5ID0gMTIsIHBhbGV0dGUgPSBjKCJibHVlIiwgInJlZCIpLCAKICAgICAgICAgICB0aXRsZSA9ICJPUyAtIGN0RE5BIE1SRC9DbGluaWNhbCBDaGFyYWN0ZXJpc3RpY3MiLCAKICAgICAgICAgICB5bGFiID0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiID0gIlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgCiAgICAgICAgICAgbGVnZW5kLmxhYnMgPSBjKCJNUkQgbmVnLCBUMS1UMywgTjAiLCAiTVJEIHBvcyBvciBUNCBvciBOMS1OMyIpLCAKICAgICAgICAgICBsZWdlbmQudGl0bGUgPSAiIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXMgPSBjKDAsIDI0KSkKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBDUiwgbGV2ZWxzPWMoIjEiLCIyIiksIGxhYmVscz1jKCJNUkQgbmVnLCBUMS1UMywgTjAiLCJNUkQgcG9zIG9yIFQ0IG9yIE4xLU4zIikpCmNveF9maXQgPC0gY294cGhmKHN1cnZfb2JqZWN0IH4gY3RETkEucENSLCBkYXRhPWNpcmNfZGF0YSkKc3VtbWFyeShjb3hfZml0KQpgYGAKCiNNdWx0aXZhcmlhdGUgY294IHJlZ3Jlc3Npb24gZm9yIFJGUyAtIGN0RE5BIE1SRCBXaW5kb3cKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJOZWdhdGl2ZSIsICJQb3NpdGl2ZSIpKQpjaXJjX2RhdGEkUHJpbVNpdGUgPC0gZmFjdG9yKGNpcmNfZGF0YSRQcmltU2l0ZSwgbGV2ZWxzPWMoIlN0b21hY2giLCJHL0oiKSkKY2lyY19kYXRhJEdlbmRlciA8LSBmYWN0b3IoY2lyY19kYXRhJEdlbmRlciwgbGV2ZWxzPWMoIk1hbGUiLCJGZW1hbGUiKSkKY2lyY19kYXRhJEFnZS5Hcm91cCA8LSBmYWN0b3IoY2lyY19kYXRhJEFnZS5Hcm91cCwgbGV2ZWxzPWMoIjIiLCIxIiksIGxhYmVscyA9IGMoIj43MCIsICLiiaQ3MCIpKQpjaXJjX2RhdGEkcFQuU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRwVC5TdGFnZSwgbGV2ZWxzPWMoIlQxLVQzIiwiVDQiKSkKY2lyY19kYXRhJHlwTlN0YXR1cyA8LSBmYWN0b3IoY2lyY19kYXRhJHlwTlN0YXR1cywgbGV2ZWxzPWMoIk4wIiwiTjEtTjMiKSkKY2lyY19kYXRhJFRSRyA8LSBmYWN0b3IoY2lyY19kYXRhJFRSRywgbGV2ZWxzPWMoIlRSRzEvMi8zIiwiVFJHNC81IikpCnN1cnZfb2JqZWN0IDwtIFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpIApjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuTVJEICsgUHJpbVNpdGUgKyBwVC5TdGFnZSArIHlwTlN0YXR1cyArIFRSRywgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LCBkYXRhID0gY2lyY19kYXRhLCBtYWluID0gIk11bHRpdmFyaWF0ZSBSZWdyZXNzaW9uIE1vZGVsIGZvciBSRlMiLCByZWZMYWJlbCA9ICJSZWZlcmVuY2UgR3JvdXAiKQp0ZXN0LnBoIDwtIGNveC56cGgoY294X2ZpdCkKYGBgCgoKI011bHRpdmFyaWF0ZSBjb3ggcmVncmVzc2lvbiBmb3IgT1MgLSBjdEROQSBNUkQgV2luZG93CmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSwgbGFiZWxzID0gYygiTmVnYXRpdmUiLCAiUG9zaXRpdmUiKSkKY2lyY19kYXRhJFByaW1TaXRlIDwtIGZhY3RvcihjaXJjX2RhdGEkUHJpbVNpdGUsIGxldmVscz1jKCJTdG9tYWNoIiwiRy9KIikpCmNpcmNfZGF0YSRHZW5kZXIgPC0gZmFjdG9yKGNpcmNfZGF0YSRHZW5kZXIsIGxldmVscz1jKCJNYWxlIiwiRmVtYWxlIikpCmNpcmNfZGF0YSRBZ2UuR3JvdXAgPC0gZmFjdG9yKGNpcmNfZGF0YSRBZ2UuR3JvdXAsIGxldmVscz1jKCIyIiwiMSIpLCBsYWJlbHMgPSBjKCI+NzAiLCAi4omkNzAiKSkKY2lyY19kYXRhJHBULlN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkcFQuU3RhZ2UsIGxldmVscz1jKCJUMS1UMyIsIlQ0IikpCmNpcmNfZGF0YSR5cE5TdGF0dXMgPC0gZmFjdG9yKGNpcmNfZGF0YSR5cE5TdGF0dXMsIGxldmVscz1jKCJOMCIsIk4xLU4zIikpCmNpcmNfZGF0YSRUUkcgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkcsIGxldmVscz1jKCJUUkcxLzIvMyIsIlRSRzQvNSIpKQpzdXJ2X29iamVjdCA8LSBTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkgCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQgKyBQcmltU2l0ZSArIHBULlN0YWdlICsgeXBOU3RhdHVzICsgVFJHLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsIGRhdGEgPSBjaXJjX2RhdGEsIG1haW4gPSAiTXVsdGl2YXJpYXRlIFJlZ3Jlc3Npb24gTW9kZWwgZm9yIE9TIiwgcmVmTGFiZWwgPSAiUmVmZXJlbmNlIEdyb3VwIikKdGVzdC5waCA8LSBjb3guenBoKGNveF9maXQpCmBgYAoKCiNNdWx0aXZhcmlhdGUgY294IHJlZ3Jlc3Npb24gZm9yIFJGUyAtIGN0RE5BIE1SRCBXaW5kb3cgVjIgKFRSRzEvMiB2cyBUUkczLTUpCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSwgbGFiZWxzID0gYygiTmVnYXRpdmUiLCAiUG9zaXRpdmUiKSkKY2lyY19kYXRhJFByaW1TaXRlIDwtIGZhY3RvcihjaXJjX2RhdGEkUHJpbVNpdGUsIGxldmVscz1jKCJTdG9tYWNoIiwiRy9KIikpCmNpcmNfZGF0YSRHZW5kZXIgPC0gZmFjdG9yKGNpcmNfZGF0YSRHZW5kZXIsIGxldmVscz1jKCJNYWxlIiwiRmVtYWxlIikpCmNpcmNfZGF0YSRBZ2UuR3JvdXAgPC0gZmFjdG9yKGNpcmNfZGF0YSRBZ2UuR3JvdXAsIGxldmVscz1jKCIyIiwiMSIpLCBsYWJlbHMgPSBjKCI+NzAiLCAi4omkNzAiKSkKY2lyY19kYXRhJHBULlN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkcFQuU3RhZ2UsIGxldmVscz1jKCJUMS1UMyIsIlQ0IikpCmNpcmNfZGF0YSR5cE5TdGF0dXMgPC0gZmFjdG9yKGNpcmNfZGF0YSR5cE5TdGF0dXMsIGxldmVscz1jKCJOMCIsIk4xLU4zIikpCmNpcmNfZGF0YSRUUkd2MiA8LSBmYWN0b3IoY2lyY19kYXRhJFRSR3YyLCBsZXZlbHMgPSBjKCJUUkcxLzIiLCAiVFJHMy80LzUiKSkKc3Vydl9vYmplY3QgPC0gU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkgCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQgKyBQcmltU2l0ZSArIHBULlN0YWdlICsgeXBOU3RhdHVzICsgVFJHdjIsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCwgZGF0YSA9IGNpcmNfZGF0YSwgbWFpbiA9ICJNdWx0aXZhcmlhdGUgUmVncmVzc2lvbiBNb2RlbCBmb3IgUkZTIiwgcmVmTGFiZWwgPSAiUmVmZXJlbmNlIEdyb3VwIikKdGVzdC5waCA8LSBjb3guenBoKGNveF9maXQpCmBgYAoKCiNSRlMgYnkgY3RETkEgYXQgdGhlIFN1cnZlaWxsYW5jZSBXaW5kb3cgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlIT0iIixdCmNpcmNfZGF0YSRERlMubW9udGhzPWNpcmNfZGF0YSRERlMubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkREZTLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5zdXJ2ZWlsbGFuY2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLnN1cnZlaWxsYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIFN1cnZlaWxsYW5jZSB3aW5kb3cgfCBBbGwgcHRzIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5zdXJ2ZWlsbGFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI09TIGJ5IGN0RE5BIGF0IHRoZSBTdXJ2ZWlsbGFuY2UgV2luZG93IC0gYWxsIHN0YWdlcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnN1cnZlaWxsYW5jZSE9IiIsXQpjaXJjX2RhdGEkRlUubW9udGhzPWNpcmNfZGF0YSRGVS5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRGVS5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLnN1cnZlaWxsYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLnN1cnZlaWxsYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgU3VydmVpbGxhbmNlIHdpbmRvdyB8IEFsbCBwdHMiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5zdXJ2ZWlsbGFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoK